Improve peformance of local variable initialisation.
[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     emitOpcode(op_initialise_locals);
272     codeBlock->globalData = m_globalData;
273
274     m_codeBlock->numConstants = functionBody->neededConstants();
275
276     const Node::FunctionStack& functionStack = functionBody->functionStack();
277     for (size_t i = 0; i < functionStack.size(); ++i) {
278         FuncDeclNode* funcDecl = functionStack[i].get();
279         const Identifier& ident = funcDecl->m_ident;
280
281         m_functions.add(ident.ustring().rep());
282         emitNewFunction(addVar(ident, false), funcDecl);
283     }
284
285     const Node::VarStack& varStack = functionBody->varStack();
286     for (size_t i = 0; i < varStack.size(); ++i) {
287         const Identifier& ident = varStack[i].first;
288         if (ident == propertyNames().arguments)
289             continue;
290         addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
291     }
292
293     Vector<Identifier>& parameters = functionBody->parameters();
294     m_nextParameter = m_nextVar - parameters.size(); // parameters are allocated prior to vars
295     m_locals.resize(localsIndex(m_nextParameter) + 1); // localsIndex of 0 => m_locals size of 1
296
297     // Add "this" as a parameter
298     m_thisRegister.setIndex(m_nextParameter);
299     ++m_nextParameter;
300     ++m_codeBlock->numParameters;
301     
302     for (size_t i = 0; i < parameters.size(); ++i)
303         addParameter(parameters[i]);
304 }
305
306 CodeGenerator::CodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
307     : m_shouldEmitDebugHooks(!!debugger)
308     , m_scopeChain(&scopeChain)
309     , m_symbolTable(symbolTable)
310     , m_scopeNode(evalNode)
311     , m_codeBlock(codeBlock)
312     , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
313     , m_finallyDepth(0)
314     , m_dynamicScopeDepth(0)
315     , m_codeType(EvalCode)
316     , m_continueDepth(0)
317     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
318     , m_lastOpcodeID(op_end)
319 {
320     emitOpcode(op_initialise_locals);
321     codeBlock->globalData = m_globalData;
322
323     m_codeBlock->numConstants = evalNode->neededConstants();
324     m_codeBlock->numVars = 1; // Allocate space for "this"
325 }
326
327 CodeGenerator::~CodeGenerator()
328 {
329 }
330
331 RegisterID* CodeGenerator::addParameter(const Identifier& ident)
332 {
333     // Parameters overwrite var declarations, but not function declarations,
334     // in the symbol table.
335     RegisterID* result = 0;
336     UString::Rep* rep = ident.ustring().rep();
337     if (!m_functions.contains(rep)) {
338         symbolTable().set(rep, m_nextParameter);
339         m_locals[localsIndex(m_nextParameter)].setIndex(m_nextParameter);
340         result = &(m_locals[localsIndex(m_nextParameter)]);
341     }
342
343     // To maintain the calling convention, we have to allocate unique space for
344     // each parameter, even if the parameter doesn't make it into the symbol table.
345     ++m_nextParameter;
346     ++m_codeBlock->numParameters;
347     return result;
348 }
349
350 RegisterID* CodeGenerator::registerForLocal(const Identifier& ident)
351 {
352     if (m_codeType == FunctionCode && ident == propertyNames().arguments)
353         m_codeBlock->needsFullScopeChain = true;
354
355     if (ident == propertyNames().thisIdentifier)
356         return &m_thisRegister;
357
358     if (!shouldOptimizeLocals())
359         return 0;
360
361     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
362     if (entry.isNull())
363         return 0;
364
365     return &m_locals[localsIndex(entry.getIndex())];
366 }
367
368 RegisterID* CodeGenerator::registerForLocalConstInit(const Identifier& ident)
369 {
370     if (m_codeType == EvalCode)
371         return 0;
372
373     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
374     ASSERT(!entry.isNull());
375
376     return &m_locals[localsIndex(entry.getIndex())];
377 }
378
379 bool CodeGenerator::isLocal(const Identifier& ident)
380 {
381     if (ident == propertyNames().thisIdentifier)
382         return true;
383     
384     return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());
385 }
386
387 bool CodeGenerator::isLocalConstant(const Identifier& ident)
388 {
389     return symbolTable().get(ident.ustring().rep()).isReadOnly();
390 }
391
392 RegisterID* CodeGenerator::newTemporary()
393 {
394     // Reclaim free register IDs.
395     while (m_temporaries.size() && !m_temporaries.last().refCount())
396         m_temporaries.removeLast();
397
398     // Allocate new register ID.
399     m_temporaries.append(m_temporaries.size() + m_codeBlock->numConstants);
400     m_codeBlock->numTemporaries = max<int>(m_codeBlock->numTemporaries, m_temporaries.size());
401     return &m_temporaries.last();
402 }
403
404 RegisterID* CodeGenerator::highestUsedRegister()
405 {
406     while (m_temporaries.size() < static_cast<unsigned>(m_codeBlock->numTemporaries))
407         m_temporaries.append(m_temporaries.size());
408     return &m_temporaries.last();
409 }
410
411 PassRefPtr<LabelID> CodeGenerator::newLabel()
412 {
413     // Reclaim free label IDs.
414     while (m_labels.size() && !m_labels.last().refCount())
415         m_labels.removeLast();
416
417     // Allocate new label ID.
418     m_labels.append(m_codeBlock);
419     return &m_labels.last();
420 }
421
422 PassRefPtr<LabelID> CodeGenerator::emitLabel(LabelID* l0)
423 {
424     l0->setLocation(instructions().size());
425     
426     // This disables peephole optimizations when an instruction is a jump target
427     m_lastOpcodeID = op_end;
428     
429     return l0;
430 }
431
432 void CodeGenerator::emitOpcode(OpcodeID opcodeID)
433 {
434     instructions().append(globalData()->machine->getOpcode(opcodeID));
435     m_lastOpcodeID = opcodeID;
436 }
437
438 void CodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
439 {
440     ASSERT(instructions().size() >= 4);
441     size_t size = instructions().size();
442     dstIndex = instructions().at(size - 3).u.operand;
443     src1Index = instructions().at(size - 2).u.operand;
444     src2Index = instructions().at(size - 1).u.operand;
445 }
446
447 void CodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
448 {
449     ASSERT(instructions().size() >= 3);
450     size_t size = instructions().size();
451     dstIndex = instructions().at(size - 2).u.operand;
452     srcIndex = instructions().at(size - 1).u.operand;
453 }
454
455 void ALWAYS_INLINE CodeGenerator::rewindBinaryOp()
456 {
457     ASSERT(instructions().size() >= 4);
458     instructions().shrink(instructions().size() - 4);
459 }
460
461 void ALWAYS_INLINE CodeGenerator::rewindUnaryOp()
462 {
463     ASSERT(instructions().size() >= 3);
464     instructions().shrink(instructions().size() - 3);
465 }
466
467 PassRefPtr<LabelID> CodeGenerator::emitJump(LabelID* target)
468 {
469     emitOpcode(target->isForwardLabel() ? op_jmp : op_loop);
470     instructions().append(target->offsetFrom(instructions().size()));
471     return target;
472 }
473
474 PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* target)
475 {
476     if (m_lastOpcodeID == op_less && !target->isForwardLabel()) {
477         int dstIndex;
478         int src1Index;
479         int src2Index;
480
481         retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
482
483         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
484             rewindBinaryOp();
485             emitOpcode(op_loop_if_less);
486             instructions().append(src1Index);
487             instructions().append(src2Index);
488             instructions().append(target->offsetFrom(instructions().size()));
489             return target;
490         }
491     } else if (m_lastOpcodeID == op_lesseq && !target->isForwardLabel()) {
492         int dstIndex;
493         int src1Index;
494         int src2Index;
495
496         retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
497
498         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
499             rewindBinaryOp();
500             emitOpcode(op_loop_if_lesseq);
501             instructions().append(src1Index);
502             instructions().append(src2Index);
503             instructions().append(target->offsetFrom(instructions().size()));
504             return target;
505         }
506     }
507
508     emitOpcode(target->isForwardLabel() ? op_jtrue : op_loop_if_true);
509     instructions().append(cond->index());
510     instructions().append(target->offsetFrom(instructions().size()));
511     return target;
512 }
513
514 PassRefPtr<LabelID> CodeGenerator::emitJumpIfFalse(RegisterID* cond, LabelID* target)
515 {
516     ASSERT(target->isForwardLabel());
517
518     if (m_lastOpcodeID == op_less) {
519         int dstIndex;
520         int src1Index;
521         int src2Index;
522
523         retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
524
525         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
526             rewindBinaryOp();
527             emitOpcode(op_jnless);
528             instructions().append(src1Index);
529             instructions().append(src2Index);
530             instructions().append(target->offsetFrom(instructions().size()));
531             return target;
532         }
533     } else if (m_lastOpcodeID == op_not) {
534         int dstIndex;
535         int srcIndex;
536
537         retrieveLastUnaryOp(dstIndex, srcIndex);
538
539         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
540             rewindUnaryOp();
541             emitOpcode(target->isForwardLabel() ? op_jtrue : op_loop_if_true);
542             instructions().append(srcIndex);
543             instructions().append(target->offsetFrom(instructions().size()));
544             return target;
545         }        
546     }
547
548     emitOpcode(op_jfalse);
549     instructions().append(cond->index());
550     instructions().append(target->offsetFrom(instructions().size()));
551     return target;
552 }
553
554 unsigned CodeGenerator::addConstant(FuncDeclNode* n)
555 {
556     // No need to explicitly unique function body nodes -- they're unique already.
557     int index = m_codeBlock->functions.size();
558     m_codeBlock->functions.append(n);
559     return index;
560 }
561
562 unsigned CodeGenerator::addConstant(FuncExprNode* n)
563 {
564     // No need to explicitly unique function expression nodes -- they're unique already.
565     int index = m_codeBlock->functionExpressions.size();
566     m_codeBlock->functionExpressions.append(n);
567     return index;
568 }
569
570 unsigned CodeGenerator::addConstant(const Identifier& ident)
571 {
572     UString::Rep* rep = ident.ustring().rep();
573     pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->identifiers.size());
574     if (result.second) // new entry
575         m_codeBlock->identifiers.append(Identifier(m_globalData, rep));
576
577     return result.first->second;
578 }
579
580 RegisterID* CodeGenerator::addConstant(JSValue* v)
581 {
582     pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(v, m_codeBlock->constantRegisters.size());
583     if (result.second) {
584         m_constants.append(m_codeBlock->constantRegisters.size());
585         m_constants.last().makeConstant();
586         m_codeBlock->constantRegisters.append(v);
587         ASSERT(m_codeBlock->constantRegisters.size() <= (unsigned) m_codeBlock->numConstants);
588         return &m_constants.last();
589     }
590
591     return &m_constants[result.first->second];
592 }
593
594 unsigned CodeGenerator::addUnexpectedConstant(JSValue* v)
595 {
596     int index = m_codeBlock->unexpectedConstants.size();
597     m_codeBlock->unexpectedConstants.append(v);
598     return index;
599 }
600
601 unsigned CodeGenerator::addRegExp(RegExp* r)
602 {
603     int index = m_codeBlock->regexps.size();
604     m_codeBlock->regexps.append(r);
605     return index;
606 }
607
608 RegisterID* CodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
609 {
610     emitOpcode(op_mov);
611     instructions().append(dst->index());
612     instructions().append(src->index());
613     return dst;
614 }
615
616 RegisterID* CodeGenerator::emitUnaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src)
617 {
618     emitOpcode(opcode);
619     instructions().append(dst->index());
620     instructions().append(src->index());
621     return dst;
622 }
623
624 RegisterID* CodeGenerator::emitPreInc(RegisterID* srcDst)
625 {
626     emitOpcode(op_pre_inc);
627     instructions().append(srcDst->index());
628     return srcDst;
629 }
630
631 RegisterID* CodeGenerator::emitPreDec(RegisterID* srcDst)
632 {
633     emitOpcode(op_pre_dec);
634     instructions().append(srcDst->index());
635     return srcDst;
636 }
637
638 RegisterID* CodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
639 {
640     emitOpcode(op_post_inc);
641     instructions().append(dst->index());
642     instructions().append(srcDst->index());
643     return dst;
644 }
645
646 RegisterID* CodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
647 {
648     emitOpcode(op_post_dec);
649     instructions().append(dst->index());
650     instructions().append(srcDst->index());
651     return dst;
652 }
653
654 RegisterID* CodeGenerator::emitBinaryOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2)
655 {
656     emitOpcode(opcode);
657     instructions().append(dst->index());
658     instructions().append(src1->index());
659     instructions().append(src2->index());
660     return dst;
661 }
662
663 RegisterID* CodeGenerator::emitEqualityOp(OpcodeID opcode, RegisterID* dst, RegisterID* src1, RegisterID* src2)
664 {
665     if (m_lastOpcodeID == op_typeof) {
666         int dstIndex;
667         int srcIndex;
668
669         retrieveLastUnaryOp(dstIndex, srcIndex);
670
671         if (src1->index() == dstIndex
672             && src1->isTemporary()
673             && static_cast<unsigned>(src2->index()) < m_codeBlock->constantRegisters.size()
674             && m_codeBlock->constantRegisters[src2->index()].jsValue(globalExec())->isString()) {
675             const UString& value = static_cast<JSString*>(m_codeBlock->constantRegisters[src2->index()].jsValue(globalExec()))->value();
676             if (value == "undefined") {
677                 rewindUnaryOp();
678                 emitOpcode(op_is_undefined);
679                 instructions().append(dst->index());
680                 instructions().append(srcIndex);
681                 return dst;
682             }
683             if (value == "boolean") {
684                 rewindUnaryOp();
685                 emitOpcode(op_is_boolean);
686                 instructions().append(dst->index());
687                 instructions().append(srcIndex);
688                 return dst;
689             }
690             if (value == "number") {
691                 rewindUnaryOp();
692                 emitOpcode(op_is_number);
693                 instructions().append(dst->index());
694                 instructions().append(srcIndex);
695                 return dst;
696             }
697             if (value == "string") {
698                 rewindUnaryOp();
699                 emitOpcode(op_is_string);
700                 instructions().append(dst->index());
701                 instructions().append(srcIndex);
702                 return dst;
703             }
704             if (value == "object") {
705                 rewindUnaryOp();
706                 emitOpcode(op_is_object);
707                 instructions().append(dst->index());
708                 instructions().append(srcIndex);
709                 return dst;
710             }
711             if (value == "function") {
712                 rewindUnaryOp();
713                 emitOpcode(op_is_function);
714                 instructions().append(dst->index());
715                 instructions().append(srcIndex);
716                 return dst;
717             }
718         }
719     }
720
721     emitOpcode(opcode);
722     instructions().append(dst->index());
723     instructions().append(src1->index());
724     instructions().append(src2->index());
725     return dst;
726 }
727
728 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, bool b)
729 {
730     return emitLoad(dst, jsBoolean(b));
731 }
732
733 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, double d)
734 {
735     return emitLoad(dst, jsNumber(globalExec(), d));
736 }
737
738 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, JSValue* v)
739 {
740     RegisterID* constantID = addConstant(v);
741     if (dst)
742         return emitMove(dst, constantID);
743     return constantID;
744 }
745
746 RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b)
747 {
748     emitOpcode(op_unexpected_load);
749     instructions().append(dst->index());
750     instructions().append(addUnexpectedConstant(jsBoolean(b)));
751     return dst;
752 }
753
754 RegisterID* CodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d)
755 {
756     emitOpcode(op_unexpected_load);
757     instructions().append(dst->index());
758     instructions().append(addUnexpectedConstant(jsNumber(globalExec(), d)));
759     return dst;
760 }
761
762 bool CodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSValue*& globalObject)
763 {
764     // Cases where we cannot statically optimise the lookup
765     if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
766         stackDepth = 0;
767         index = missingSymbolMarker();
768
769         if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
770             ScopeChainIterator iter = m_scopeChain->begin();
771             globalObject = *iter;
772             ASSERT((++iter) == m_scopeChain->end());
773         }
774         return false;
775     }
776
777     size_t depth = 0;
778     
779     ScopeChainIterator iter = m_scopeChain->begin();
780     ScopeChainIterator end = m_scopeChain->end();
781     for (; iter != end; ++iter, ++depth) {
782         JSObject* currentScope = *iter;
783         if (!currentScope->isVariableObject())
784             break;
785         JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
786         SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.ustring().rep());
787
788         // Found the property
789         if (!entry.isNull()) {
790             if (entry.isReadOnly() && forWriting) {
791                 stackDepth = 0;
792                 index = missingSymbolMarker();
793                 if (++iter == end)
794                     globalObject = currentVariableObject;
795                 return false;
796             }
797             stackDepth = depth;
798             index = entry.getIndex();
799             if (++iter == end)
800                 globalObject = currentVariableObject;
801             return true;
802         }
803         if (currentVariableObject->isDynamicScope())
804             break;
805     }
806
807     // Can't locate the property but we're able to avoid a few lookups
808     stackDepth = depth;
809     index = missingSymbolMarker();
810     JSObject* scope = *iter;
811     if (++iter == end)
812         globalObject = scope;
813     return true;
814 }
815
816 RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
817
818     emitOpcode(op_instanceof);
819     instructions().append(dst->index());
820     instructions().append(value->index());
821     instructions().append(base->index());
822     instructions().append(basePrototype->index());
823     return dst;
824 }
825
826 RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
827 {
828     size_t depth = 0;
829     int index = 0;
830     JSValue* globalObject = 0;
831     if (!findScopedProperty(property, index, depth, false, globalObject) && !globalObject) {
832         // We can't optimise at all :-(
833         emitOpcode(op_resolve);
834         instructions().append(dst->index());
835         instructions().append(addConstant(property));
836         return dst;
837     }
838
839     if (index != missingSymbolMarker()) {
840         // Directly index the property lookup across multiple scopes.  Yay!
841         return emitGetScopedVar(dst, depth, index, globalObject);
842     }
843
844     if (globalObject) {
845         m_codeBlock->structureIDInstructions.append(instructions().size());
846         emitOpcode(op_resolve_global);
847         instructions().append(dst->index());
848         instructions().append(static_cast<JSCell*>(globalObject));
849         instructions().append(addConstant(property));
850         instructions().append(0);
851         instructions().append(0);
852         return dst;
853     }
854
855     // In this case we are at least able to drop a few scope chains from the
856     // lookup chain, although we still need to hash from then on.
857     emitOpcode(op_resolve_skip);
858     instructions().append(dst->index());
859     instructions().append(addConstant(property));
860     instructions().append(depth);
861     return dst;
862 }
863
864 RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue* globalObject)
865 {
866     if (globalObject) {
867         emitOpcode(op_get_global_var);
868         instructions().append(dst->index());
869         instructions().append(static_cast<JSCell*>(globalObject));
870         instructions().append(index);
871         return dst;
872     }
873
874     emitOpcode(op_get_scoped_var);
875     instructions().append(dst->index());
876     instructions().append(index);
877     instructions().append(depth);
878     return dst;
879 }
880
881 RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue* globalObject)
882 {
883     if (globalObject) {
884         emitOpcode(op_put_global_var);
885         instructions().append(static_cast<JSCell*>(globalObject));
886         instructions().append(index);
887         instructions().append(value->index());
888         return value;
889     }
890     emitOpcode(op_put_scoped_var);
891     instructions().append(index);
892     instructions().append(depth);
893     instructions().append(value->index());
894     return value;
895 }
896
897 RegisterID* CodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
898 {
899     emitOpcode(op_resolve_base);
900     instructions().append(dst->index());
901     instructions().append(addConstant(property));
902     return dst;
903 }
904
905 RegisterID* CodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
906 {
907     emitOpcode(op_resolve_with_base);
908     instructions().append(baseDst->index());
909     instructions().append(propDst->index());
910     instructions().append(addConstant(property));
911     return baseDst;
912 }
913
914 RegisterID* CodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
915 {
916     emitOpcode(op_resolve_func);
917     instructions().append(baseDst->index());
918     instructions().append(funcDst->index());
919     instructions().append(addConstant(property));
920     return baseDst;
921 }
922
923 RegisterID* CodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
924 {
925     m_codeBlock->structureIDInstructions.append(instructions().size());
926
927     emitOpcode(op_get_by_id);
928     instructions().append(dst->index());
929     instructions().append(base->index());
930     instructions().append(addConstant(property));
931     instructions().append(0);
932     instructions().append(0);
933     instructions().append(0);
934     instructions().append(0);
935     return dst;
936 }
937
938 RegisterID* CodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
939 {
940     m_codeBlock->structureIDInstructions.append(instructions().size());
941
942     emitOpcode(op_put_by_id);
943     instructions().append(base->index());
944     instructions().append(addConstant(property));
945     instructions().append(value->index());
946     instructions().append(0);
947     instructions().append(0);
948     instructions().append(0);
949     instructions().append(0);
950     return value;
951 }
952
953 RegisterID* CodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
954 {
955     emitOpcode(op_put_getter);
956     instructions().append(base->index());
957     instructions().append(addConstant(property));
958     instructions().append(value->index());
959     return value;
960 }
961
962 RegisterID* CodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
963 {
964     emitOpcode(op_put_setter);
965     instructions().append(base->index());
966     instructions().append(addConstant(property));
967     instructions().append(value->index());
968     return value;
969 }
970
971 RegisterID* CodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
972 {
973     emitOpcode(op_del_by_id);
974     instructions().append(dst->index());
975     instructions().append(base->index());
976     instructions().append(addConstant(property));
977     return dst;
978 }
979
980 RegisterID* CodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
981 {
982     emitOpcode(op_get_by_val);
983     instructions().append(dst->index());
984     instructions().append(base->index());
985     instructions().append(property->index());
986     return dst;
987 }
988
989 RegisterID* CodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
990 {
991     emitOpcode(op_put_by_val);
992     instructions().append(base->index());
993     instructions().append(property->index());
994     instructions().append(value->index());
995     return value;
996 }
997
998 RegisterID* CodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
999 {
1000     emitOpcode(op_del_by_val);
1001     instructions().append(dst->index());
1002     instructions().append(base->index());
1003     instructions().append(property->index());
1004     return dst;
1005 }
1006
1007 RegisterID* CodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1008 {
1009     emitOpcode(op_put_by_index);
1010     instructions().append(base->index());
1011     instructions().append(index);
1012     instructions().append(value->index());
1013     return value;
1014 }
1015
1016 RegisterID* CodeGenerator::emitNewObject(RegisterID* dst)
1017 {
1018     emitOpcode(op_new_object);
1019     instructions().append(dst->index());
1020     return dst;
1021 }
1022
1023 RegisterID* CodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements)
1024 {
1025     Vector<RefPtr<RegisterID>, 16> argv;
1026     for (ElementNode* n = elements; n; n = n->next()) {
1027         if (n->elision())
1028             break;
1029         argv.append(newTemporary());
1030         emitNode(argv.last().get(), n->value());
1031     }
1032     emitOpcode(op_new_array);
1033     instructions().append(dst->index());
1034     instructions().append(argv.size() ? argv[0]->index() : 0); // argv
1035     instructions().append(argv.size()); // argc
1036     return dst;
1037 }
1038
1039 RegisterID* CodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n)
1040 {
1041     emitOpcode(op_new_func);
1042     instructions().append(dst->index());
1043     instructions().append(addConstant(n));
1044     return dst;
1045 }
1046
1047 RegisterID* CodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
1048 {
1049     emitOpcode(op_new_regexp);
1050     instructions().append(dst->index());
1051     instructions().append(addRegExp(regExp));
1052     return dst;
1053 }
1054
1055
1056 RegisterID* CodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
1057 {
1058     emitOpcode(op_new_func_exp);
1059     instructions().append(r0->index());
1060     instructions().append(addConstant(n));
1061     return r0;
1062 }
1063
1064 RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1065 {
1066     return emitCall(op_call, dst, func, base, argumentsNode, divot, startOffset, endOffset);
1067 }
1068
1069 RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1070 {
1071     return emitCall(op_call_eval, dst, func, base, argumentsNode, divot, startOffset, endOffset);
1072 }
1073
1074 RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1075 {
1076     ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
1077     
1078     // Ordinarily, we might ref "func" and "base", to avoid allocating new
1079     // temporaries in the same registers. In this case, though, we actually
1080     // want the call frame we allocate to overlap "func" and "base", if they're
1081     // not otherwise referenced. op_call will read "func" and "base" before
1082     // writing out the call frame, so this is safe.
1083
1084     // Reserve space for call frame.
1085     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1086     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1087         callFrame.append(newTemporary());
1088
1089     // Generate code for arguments.
1090     Vector<RefPtr<RegisterID>, 16> argv;
1091     argv.append(newTemporary()); // reserve space for "this"
1092     for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) {
1093         argv.append(newTemporary());
1094         emitNode(argv.last().get(), n);
1095     }
1096
1097     emitExpressionInfo(divot, startOffset, endOffset);
1098     emitOpcode(opcodeID);
1099     instructions().append(dst->index());
1100     instructions().append(func->index());
1101     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.
1102     instructions().append(argv[0]->index()); // argv
1103     instructions().append(argv.size()); // argc
1104     return dst;
1105 }
1106
1107 RegisterID* CodeGenerator::emitUnaryNoDstOp(OpcodeID opcode, RegisterID* src)
1108 {
1109     emitOpcode(opcode);
1110     instructions().append(src->index());
1111     return src;
1112 }
1113
1114 RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1115 {
1116     ASSERT(func->refCount());
1117
1118     // Reserve space for prototype
1119     RefPtr<RegisterID> funcProto = newTemporary();
1120
1121     // Reserve space for call frame.
1122     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1123     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1124         callFrame.append(newTemporary());
1125
1126     // Generate code for arguments.
1127     Vector<RefPtr<RegisterID>, 16> argv;
1128     argv.append(newTemporary()); // reserve space for "this"
1129     for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() : 0; n; n = n->m_next.get()) {
1130         argv.append(newTemporary());
1131         emitNode(argv.last().get(), n);
1132     }
1133
1134     emitExpressionInfo(divot, startOffset, endOffset);
1135     emitGetById(funcProto.get(), func, globalExec()->propertyNames().prototype);
1136
1137     emitExpressionInfo(divot, startOffset, endOffset);
1138     emitOpcode(op_construct);
1139     instructions().append(dst->index());
1140     instructions().append(func->index());
1141     instructions().append(funcProto->index());
1142     instructions().append(argv[0]->index()); // argv
1143     instructions().append(argv.size()); // argc
1144     
1145     emitOpcode(op_construct_verify);
1146     instructions().append(dst->index());
1147     instructions().append(argv[0]->index());
1148
1149     return dst;
1150 }
1151
1152 RegisterID* CodeGenerator::emitPushScope(RegisterID* scope)
1153 {
1154     m_codeBlock->needsFullScopeChain = true;
1155     ControlFlowContext context;
1156     context.isFinallyBlock = false;
1157     m_scopeContextStack.append(context);
1158     m_dynamicScopeDepth++;
1159
1160     return emitUnaryNoDstOp(op_push_scope, scope);
1161 }
1162
1163 void CodeGenerator::emitPopScope()
1164 {
1165     ASSERT(m_scopeContextStack.size());
1166     ASSERT(!m_scopeContextStack.last().isFinallyBlock);
1167
1168     emitOpcode(op_pop_scope);
1169
1170     m_scopeContextStack.removeLast();
1171     m_dynamicScopeDepth--;
1172 }
1173
1174 void CodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine)
1175 {
1176     if (!m_shouldEmitDebugHooks)
1177         return;
1178     emitOpcode(op_debug);
1179     instructions().append(debugHookID);
1180     instructions().append(firstLine);
1181     instructions().append(lastLine);
1182 }
1183
1184 void CodeGenerator::pushFinallyContext(LabelID* target, RegisterID* retAddrDst)
1185 {
1186     ControlFlowContext scope;
1187     scope.isFinallyBlock = true;
1188     FinallyContext context = { target, retAddrDst };
1189     scope.finallyContext = context;
1190     m_scopeContextStack.append(scope);
1191     m_finallyDepth++;
1192 }
1193
1194 void CodeGenerator::popFinallyContext()
1195 {
1196     ASSERT(m_scopeContextStack.size());
1197     ASSERT(m_scopeContextStack.last().isFinallyBlock);
1198     ASSERT(m_finallyDepth > 0);
1199     m_scopeContextStack.removeLast();
1200     m_finallyDepth--;
1201 }
1202
1203 void CodeGenerator::pushJumpContext(LabelStack* labels, LabelID* continueTarget, LabelID* breakTarget, bool isValidUnlabeledBreakTarget)
1204 {
1205     JumpContext context = { labels, continueTarget, breakTarget, scopeDepth(), isValidUnlabeledBreakTarget };
1206     m_jumpContextStack.append(context);
1207     if (continueTarget)
1208         m_continueDepth++;
1209 }
1210
1211 void CodeGenerator::popJumpContext()
1212 {
1213     ASSERT(m_jumpContextStack.size());
1214     if (m_jumpContextStack.last().continueTarget)
1215         m_continueDepth--;
1216     m_jumpContextStack.removeLast();
1217 }
1218
1219 JumpContext* CodeGenerator::jumpContextForContinue(const Identifier& label)
1220 {
1221     if(!m_jumpContextStack.size())
1222         return 0;
1223
1224     if (label.isEmpty()) {
1225         for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1226             JumpContext* scope = &m_jumpContextStack[i];
1227             if (scope->continueTarget)
1228                 return scope;
1229         }
1230         return 0;
1231     }
1232
1233     for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1234         JumpContext* scope = &m_jumpContextStack[i];
1235         if (scope->labels->contains(label))
1236             return scope;
1237     }
1238     return 0;
1239 }
1240
1241 JumpContext* CodeGenerator::jumpContextForBreak(const Identifier& label)
1242 {
1243     if(!m_jumpContextStack.size())
1244         return 0;
1245
1246     if (label.isEmpty()) {
1247         for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1248             JumpContext* scope = &m_jumpContextStack[i];
1249             if (scope->isValidUnlabeledBreakTarget)
1250                 return scope;
1251         }
1252         return 0;
1253     }
1254
1255     for (int i = m_jumpContextStack.size() - 1; i >= 0; i--) {
1256         JumpContext* scope = &m_jumpContextStack[i];
1257         if (scope->labels->contains(label))
1258             return scope;
1259     }
1260     return 0;
1261 }
1262
1263 PassRefPtr<LabelID> CodeGenerator::emitComplexJumpScopes(LabelID* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
1264 {
1265     while (topScope > bottomScope) {
1266         // First we count the number of dynamic scopes we need to remove to get
1267         // to a finally block.
1268         int nNormalScopes = 0;
1269         while (topScope > bottomScope) {
1270             if (topScope->isFinallyBlock)
1271                 break;
1272             ++nNormalScopes;
1273             --topScope;
1274         }
1275
1276         if (nNormalScopes) {
1277             // We need to remove a number of dynamic scopes to get to the next
1278             // finally block
1279             emitOpcode(op_jmp_scopes);
1280             instructions().append(nNormalScopes);
1281
1282             // If topScope == bottomScope then there isn't actually a finally block
1283             // left to emit, so make the jmp_scopes jump directly to the target label
1284             if (topScope == bottomScope) {
1285                 instructions().append(target->offsetFrom(instructions().size()));
1286                 return target;
1287             }
1288
1289             // Otherwise we just use jmp_scopes to pop a group of scopes and go
1290             // to the next instruction
1291             RefPtr<LabelID> nextInsn = newLabel();
1292             instructions().append(nextInsn->offsetFrom(instructions().size()));
1293             emitLabel(nextInsn.get());
1294         }
1295
1296         // To get here there must be at least one finally block present
1297         do {
1298             ASSERT(topScope->isFinallyBlock);
1299             emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
1300             --topScope;
1301             if (!topScope->isFinallyBlock)
1302                 break;
1303         } while (topScope > bottomScope);
1304     }
1305     return emitJump(target);
1306 }
1307
1308 PassRefPtr<LabelID> CodeGenerator::emitJumpScopes(LabelID* target, int targetScopeDepth)
1309 {
1310     ASSERT(scopeDepth() - targetScopeDepth >= 0);
1311     ASSERT(target->isForwardLabel());
1312
1313     size_t scopeDelta = scopeDepth() - targetScopeDepth;
1314     ASSERT(scopeDelta <= m_scopeContextStack.size());
1315     if (!scopeDelta)
1316         return emitJump(target);
1317
1318     if (m_finallyDepth)
1319         return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
1320
1321     emitOpcode(op_jmp_scopes);
1322     instructions().append(scopeDelta);
1323     instructions().append(target->offsetFrom(instructions().size()));
1324     return target;
1325 }
1326
1327 RegisterID* CodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, LabelID* target)
1328 {
1329     emitOpcode(op_next_pname);
1330     instructions().append(dst->index());
1331     instructions().append(iter->index());
1332     instructions().append(target->offsetFrom(instructions().size()));
1333     return dst;
1334 }
1335
1336 RegisterID* CodeGenerator::emitCatch(RegisterID* targetRegister, LabelID* start, LabelID* end)
1337 {
1338     HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth, 0 };
1339     exceptionHandlers().append(info);
1340     emitOpcode(op_catch);
1341     instructions().append(targetRegister->index());
1342     return targetRegister;
1343 }
1344
1345 RegisterID* CodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue* message)
1346 {
1347     emitOpcode(op_new_error);
1348     instructions().append(dst->index());
1349     instructions().append(static_cast<int>(type));
1350     instructions().append(addUnexpectedConstant(message));
1351     return dst;
1352 }
1353
1354 PassRefPtr<LabelID> CodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, LabelID* finally)
1355 {
1356     emitOpcode(op_jsr);
1357     instructions().append(retAddrDst->index());
1358     instructions().append(finally->offsetFrom(instructions().size()));
1359     return finally;
1360 }
1361
1362 void CodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
1363 {
1364     emitOpcode(op_sret);
1365     instructions().append(retAddrSrc->index());
1366 }
1367
1368 void CodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value)
1369 {
1370     m_codeBlock->needsFullScopeChain = true;
1371     ControlFlowContext context;
1372     context.isFinallyBlock = false;
1373     m_scopeContextStack.append(context);
1374     m_dynamicScopeDepth++;
1375     
1376     emitOpcode(op_push_new_scope);
1377     instructions().append(dst->index());
1378     instructions().append(addConstant(property));
1379     instructions().append(value->index());
1380 }
1381
1382 void CodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
1383 {
1384     SwitchInfo info = { instructions().size(), type };
1385     switch (type) {
1386         case SwitchInfo::SwitchImmediate:
1387             emitOpcode(op_switch_imm);
1388             break;
1389         case SwitchInfo::SwitchCharacter:
1390             emitOpcode(op_switch_char);
1391             break;
1392         case SwitchInfo::SwitchString:
1393             emitOpcode(op_switch_string);
1394             break;
1395         default:
1396             ASSERT_NOT_REACHED();
1397     }
1398
1399     instructions().append(0); // place holder for table index
1400     instructions().append(0); // place holder for default target    
1401     instructions().append(scrutineeRegister->index());
1402     m_switchContextStack.append(info);
1403 }
1404
1405 static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
1406 {
1407     UNUSED_PARAM(max);
1408     ASSERT(node->isNumber());
1409     double value = static_cast<NumberNode*>(node)->value();
1410     ASSERT(JSImmediate::from(value));
1411     int32_t key = static_cast<int32_t>(value);
1412     ASSERT(key == value);
1413     ASSERT(key >= min);
1414     ASSERT(key <= max);
1415     return key - min;
1416 }
1417
1418 static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1419 {
1420     jumpTable.min = min;
1421     jumpTable.branchOffsets.resize(max - min + 1);
1422     jumpTable.branchOffsets.fill(0);
1423     for (uint32_t i = 0; i < clauseCount; ++i) {
1424         // We're emitting this after the clause labels should have been fixed, so 
1425         // the labels should not be "forward" references
1426         ASSERT(!labels[i]->isForwardLabel());
1427         jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
1428     }
1429 }
1430
1431 static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
1432 {
1433     UNUSED_PARAM(max);
1434     ASSERT(node->isString());
1435     UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep();
1436     ASSERT(clause->size() == 1);
1437     
1438     int32_t key = clause->data()[0];
1439     ASSERT(key >= min);
1440     ASSERT(key <= max);
1441     return key - min;
1442 }
1443
1444 static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1445 {
1446     jumpTable.min = min;
1447     jumpTable.branchOffsets.resize(max - min + 1);
1448     jumpTable.branchOffsets.fill(0);
1449     for (uint32_t i = 0; i < clauseCount; ++i) {
1450         // We're emitting this after the clause labels should have been fixed, so 
1451         // the labels should not be "forward" references
1452         ASSERT(!labels[i]->isForwardLabel());
1453         jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
1454     }
1455 }
1456
1457 static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes)
1458 {
1459     for (uint32_t i = 0; i < clauseCount; ++i) {
1460         // We're emitting this after the clause labels should have been fixed, so 
1461         // the labels should not be "forward" references
1462         ASSERT(!labels[i]->isForwardLabel());
1463         
1464         ASSERT(nodes[i]->isString());
1465         UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
1466         OffsetLocation location;
1467         location.branchOffset = labels[i]->offsetFrom(switchAddress);
1468 #if ENABLE(CTI)
1469         location.ctiOffset = 0;
1470 #endif
1471         jumpTable.offsetTable.add(clause, location);
1472     }
1473 }
1474
1475 void CodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<LabelID>* labels, ExpressionNode** nodes, LabelID* defaultLabel, int32_t min, int32_t max)
1476 {
1477     SwitchInfo switchInfo = m_switchContextStack.last();
1478     m_switchContextStack.removeLast();
1479     if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
1480         instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->immediateSwitchJumpTables.size();
1481         instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3);
1482
1483         m_codeBlock->immediateSwitchJumpTables.append(SimpleJumpTable());
1484         SimpleJumpTable& jumpTable = m_codeBlock->immediateSwitchJumpTables.last();
1485
1486         prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes, min, max);
1487     } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
1488         instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->characterSwitchJumpTables.size();
1489         instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3);
1490         
1491         m_codeBlock->characterSwitchJumpTables.append(SimpleJumpTable());
1492         SimpleJumpTable& jumpTable = m_codeBlock->characterSwitchJumpTables.last();
1493
1494         prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes, min, max);
1495     } else {
1496         ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
1497         instructions()[switchInfo.opcodeOffset + 1] = m_codeBlock->stringSwitchJumpTables.size();
1498         instructions()[switchInfo.opcodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.opcodeOffset + 3);
1499
1500         m_codeBlock->stringSwitchJumpTables.append(StringJumpTable());
1501         StringJumpTable& jumpTable = m_codeBlock->stringSwitchJumpTables.last();
1502
1503         prepareJumpTableForStringSwitch(jumpTable, switchInfo.opcodeOffset + 3, clauseCount, labels, nodes);
1504     }
1505 }
1506
1507 } // namespace JSC