1/*
2 * Copyright (C) 2008, 2009 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 "BytecodeGenerator.h"
32
33#include "BatchedTransitionOptimizer.h"
34#include "PrototypeFunction.h"
35#include "JSFunction.h"
36#include "Interpreter.h"
37#include "UString.h"
38
39using namespace std;
40
41namespace JSC {
42
43/*
44    The layout of a register frame looks like this:
45
46    For
47
48    function f(x, y) {
49        var v1;
50        function g() { }
51        var v2;
52        return (x) * (y);
53    }
54
55    assuming (x) and (y) generated temporaries t1 and t2, you would have
56
57    ------------------------------------
58    |  x |  y |  g | v2 | v1 | t1 | t2 | <-- value held
59    ------------------------------------
60    | -5 | -4 | -3 | -2 | -1 | +0 | +1 | <-- register index
61    ------------------------------------
62    | params->|<-locals      | temps->
63
64    Because temporary registers are allocated in a stack-like fashion, we
65    can reclaim them with a simple popping algorithm. The same goes for labels.
66    (We never reclaim parameter or local registers, because parameters and
67    locals are DontDelete.)
68
69    The register layout before a function call looks like this:
70
71    For
72
73    function f(x, y)
74    {
75    }
76
77    f(1);
78
79    >                        <------------------------------
80    <                        >  reserved: call frame  |  1 | <-- value held
81    >         >snip<         <------------------------------
82    <                        > +0 | +1 | +2 | +3 | +4 | +5 | <-- register index
83    >                        <------------------------------
84    | params->|<-locals      | temps->
85
86    The call instruction fills in the "call frame" registers. It also pads
87    missing arguments at the end of the call:
88
89    >                        <-----------------------------------
90    <                        >  reserved: call frame  |  1 |  ? | <-- value held ("?" stands for "undefined")
91    >         >snip<         <-----------------------------------
92    <                        > +0 | +1 | +2 | +3 | +4 | +5 | +6 | <-- register index
93    >                        <-----------------------------------
94    | params->|<-locals      | temps->
95
96    After filling in missing arguments, the call instruction sets up the new
97    stack frame to overlap the end of the old stack frame:
98
99                             |---------------------------------->                        <
100                             |  reserved: call frame  |  1 |  ? <                        > <-- value held ("?" stands for "undefined")
101                             |---------------------------------->         >snip<         <
102                             | -7 | -6 | -5 | -4 | -3 | -2 | -1 <                        > <-- register index
103                             |---------------------------------->                        <
104                             |                        | params->|<-locals       | temps->
105
106    That way, arguments are "copied" into the callee's stack frame for free.
107
108    If the caller supplies too many arguments, this trick doesn't work. The
109    extra arguments protrude into space reserved for locals and temporaries.
110    In that case, the call instruction makes a real copy of the call frame header,
111    along with just the arguments expected by the callee, leaving the original
112    call frame header and arguments behind. (The call instruction can't just discard
113    extra arguments, because the "arguments" object may access them later.)
114    This copying strategy ensures that all named values will be at the indices
115    expected by the callee.
116*/
117
118#ifndef NDEBUG
119static bool s_dumpsGeneratedCode = false;
120#endif
121
122void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
123{
124#ifndef NDEBUG
125    s_dumpsGeneratedCode = dumpsGeneratedCode;
126#else
127    UNUSED_PARAM(dumpsGeneratedCode);
128#endif
129}
130
131bool BytecodeGenerator::dumpsGeneratedCode()
132{
133#ifndef NDEBUG
134    return s_dumpsGeneratedCode;
135#else
136    return false;
137#endif
138}
139
140void BytecodeGenerator::generate()
141{
142    m_codeBlock->setThisRegister(m_thisRegister.index());
143
144    m_scopeNode->emitBytecode(*this);
145
146#ifndef NDEBUG
147    m_codeBlock->setInstructionCount(m_codeBlock->instructions().size());
148
149    if (s_dumpsGeneratedCode)
150        m_codeBlock->dump(m_scopeChain->globalObject()->globalExec());
151#endif
152
153    if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
154        symbolTable().clear();
155
156    m_codeBlock->setIsNumericCompareFunction(instructions() == m_globalData->numericCompareFunction(m_scopeChain->globalObject()->globalExec()));
157
158#if !ENABLE(OPCODE_SAMPLING)
159    if (!m_regeneratingForExceptionInfo && (m_codeType == FunctionCode || m_codeType == EvalCode))
160        m_codeBlock->clearExceptionInfo();
161#endif
162
163    m_codeBlock->shrinkToFit();
164}
165
166bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
167{
168    int index = m_calleeRegisters.size();
169    SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
170    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
171
172    if (!result.second) {
173        r0 = &registerFor(result.first->second.getIndex());
174        return false;
175    }
176
177    ++m_codeBlock->m_numVars;
178    r0 = newRegister();
179    return true;
180}
181
182bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
183{
184    int index = m_nextGlobalIndex;
185    SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
186    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
187
188    if (!result.second)
189        index = result.first->second.getIndex();
190    else {
191        --m_nextGlobalIndex;
192        m_globals.append(index + m_globalVarStorageOffset);
193    }
194
195    r0 = &registerFor(index);
196    return result.second;
197}
198
199void BytecodeGenerator::preserveLastVar()
200{
201    if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
202        m_lastVar = &m_calleeRegisters.last();
203}
204
205BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
206    : m_shouldEmitDebugHooks(!!debugger)
207    , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
208    , m_scopeChain(&scopeChain)
209    , m_symbolTable(symbolTable)
210    , m_scopeNode(programNode)
211    , m_codeBlock(codeBlock)
212    , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
213    , m_finallyDepth(0)
214    , m_dynamicScopeDepth(0)
215    , m_baseScopeDepth(0)
216    , m_codeType(GlobalCode)
217    , m_nextGlobalIndex(-1)
218    , m_nextConstantOffset(0)
219    , m_globalConstantIndex(0)
220    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
221    , m_lastOpcodeID(op_end)
222    , m_emitNodeDepth(0)
223    , m_regeneratingForExceptionInfo(false)
224    , m_codeBlockBeingRegeneratedFrom(0)
225{
226    if (m_shouldEmitDebugHooks)
227        m_codeBlock->setNeedsFullScopeChain(true);
228
229    emitOpcode(op_enter);
230    codeBlock->setGlobalData(m_globalData);
231
232    // FIXME: Move code that modifies the global object to Interpreter::execute.
233
234    m_codeBlock->m_numParameters = 1; // Allocate space for "this"
235
236    JSGlobalObject* globalObject = scopeChain.globalObject();
237    ExecState* exec = globalObject->globalExec();
238    RegisterFile* registerFile = &exec->globalData().interpreter->registerFile();
239
240    // Shift register indexes in generated code to elide registers allocated by intermediate stack frames.
241    m_globalVarStorageOffset = -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters - registerFile->size();
242
243    // Add previously defined symbols to bookkeeping.
244    m_globals.grow(symbolTable->size());
245    SymbolTable::iterator end = symbolTable->end();
246    for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
247        registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset);
248
249    BatchedTransitionOptimizer optimizer(globalObject);
250
251    const VarStack& varStack = programNode->varStack();
252    const FunctionStack& functionStack = programNode->functionStack();
253    bool canOptimizeNewGlobals = symbolTable->size() + functionStack.size() + varStack.size() < registerFile->maxGlobals();
254    if (canOptimizeNewGlobals) {
255        // Shift new symbols so they get stored prior to existing symbols.
256        m_nextGlobalIndex -= symbolTable->size();
257
258        for (size_t i = 0; i < functionStack.size(); ++i) {
259            FunctionBodyNode* function = functionStack[i];
260            globalObject->removeDirect(function->ident()); // Make sure our new function is not shadowed by an old property.
261            emitNewFunction(addGlobalVar(function->ident(), false), function);
262        }
263
264        Vector<RegisterID*, 32> newVars;
265        for (size_t i = 0; i < varStack.size(); ++i)
266            if (!globalObject->hasProperty(exec, *varStack[i].first))
267                newVars.append(addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
268
269        preserveLastVar();
270
271        for (size_t i = 0; i < newVars.size(); ++i)
272            emitLoad(newVars[i], jsUndefined());
273    } else {
274        for (size_t i = 0; i < functionStack.size(); ++i) {
275            FunctionBodyNode* function = functionStack[i];
276            globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain.node()), DontDelete);
277        }
278        for (size_t i = 0; i < varStack.size(); ++i) {
279            if (globalObject->hasProperty(exec, *varStack[i].first))
280                continue;
281            int attributes = DontDelete;
282            if (varStack[i].second & DeclarationStacks::IsConstant)
283                attributes |= ReadOnly;
284            globalObject->putWithAttributes(exec, *varStack[i].first, jsUndefined(), attributes);
285        }
286
287        preserveLastVar();
288    }
289}
290
291BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
292    : m_shouldEmitDebugHooks(!!debugger)
293    , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
294    , m_scopeChain(&scopeChain)
295    , m_symbolTable(symbolTable)
296    , m_scopeNode(functionBody)
297    , m_codeBlock(codeBlock)
298    , m_finallyDepth(0)
299    , m_dynamicScopeDepth(0)
300    , m_baseScopeDepth(0)
301    , m_codeType(FunctionCode)
302    , m_nextConstantOffset(0)
303    , m_globalConstantIndex(0)
304    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
305    , m_lastOpcodeID(op_end)
306    , m_emitNodeDepth(0)
307    , m_regeneratingForExceptionInfo(false)
308    , m_codeBlockBeingRegeneratedFrom(0)
309{
310    if (m_shouldEmitDebugHooks)
311        m_codeBlock->setNeedsFullScopeChain(true);
312
313    codeBlock->setGlobalData(m_globalData);
314
315    bool usesArguments = functionBody->usesArguments();
316    codeBlock->setUsesArguments(usesArguments);
317    if (usesArguments) {
318        m_argumentsRegister.setIndex(RegisterFile::OptionalCalleeArguments);
319        addVar(propertyNames().arguments, false);
320    }
321
322    if (m_codeBlock->needsFullScopeChain()) {
323        ++m_codeBlock->m_numVars;
324        m_activationRegisterIndex = newRegister()->index();
325        emitOpcode(op_enter_with_activation);
326        instructions().append(m_activationRegisterIndex);
327    } else
328        emitOpcode(op_enter);
329
330    if (usesArguments) {
331        emitOpcode(op_init_arguments);
332
333        // The debugger currently retrieves the arguments object from an activation rather than pulling
334        // it from a call frame.  In the long-term it should stop doing that (<rdar://problem/6911886>),
335        // but for now we force eager creation of the arguments object when debugging.
336        if (m_shouldEmitDebugHooks)
337            emitOpcode(op_create_arguments);
338    }
339
340    const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
341    for (size_t i = 0; i < functionStack.size(); ++i) {
342        FunctionBodyNode* function = functionStack[i];
343        const Identifier& ident = function->ident();
344        m_functions.add(ident.ustring().rep());
345        emitNewFunction(addVar(ident, false), function);
346    }
347
348    const DeclarationStacks::VarStack& varStack = functionBody->varStack();
349    for (size_t i = 0; i < varStack.size(); ++i)
350        addVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
351
352    FunctionParameters& parameters = *functionBody->parameters();
353    size_t parameterCount = parameters.size();
354    m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
355    m_parameters.grow(1 + parameterCount); // reserve space for "this"
356
357    // Add "this" as a parameter
358    m_thisRegister.setIndex(m_nextParameterIndex);
359    ++m_nextParameterIndex;
360    ++m_codeBlock->m_numParameters;
361
362    if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
363        emitOpcode(op_convert_this);
364        instructions().append(m_thisRegister.index());
365    }
366
367    for (size_t i = 0; i < parameterCount; ++i)
368        addParameter(parameters[i]);
369
370    preserveLastVar();
371}
372
373BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
374    : m_shouldEmitDebugHooks(!!debugger)
375    , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
376    , m_scopeChain(&scopeChain)
377    , m_symbolTable(symbolTable)
378    , m_scopeNode(evalNode)
379    , m_codeBlock(codeBlock)
380    , m_thisRegister(RegisterFile::ProgramCodeThisRegister)
381    , m_finallyDepth(0)
382    , m_dynamicScopeDepth(0)
383    , m_baseScopeDepth(codeBlock->baseScopeDepth())
384    , m_codeType(EvalCode)
385    , m_nextConstantOffset(0)
386    , m_globalConstantIndex(0)
387    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
388    , m_lastOpcodeID(op_end)
389    , m_emitNodeDepth(0)
390    , m_regeneratingForExceptionInfo(false)
391    , m_codeBlockBeingRegeneratedFrom(0)
392{
393    if (m_shouldEmitDebugHooks || m_baseScopeDepth)
394        m_codeBlock->setNeedsFullScopeChain(true);
395
396    emitOpcode(op_enter);
397    codeBlock->setGlobalData(m_globalData);
398    m_codeBlock->m_numParameters = 1; // Allocate space for "this"
399
400    const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
401    for (size_t i = 0; i < functionStack.size(); ++i)
402        m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i]));
403
404    const DeclarationStacks::VarStack& varStack = evalNode->varStack();
405    unsigned numVariables = varStack.size();
406    Vector<Identifier> variables;
407    variables.reserveCapacity(numVariables);
408    for (size_t i = 0; i < numVariables; ++i)
409        variables.append(*varStack[i].first);
410    codeBlock->adoptVariables(variables);
411
412    preserveLastVar();
413}
414
415RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
416{
417    // Parameters overwrite var declarations, but not function declarations.
418    RegisterID* result = 0;
419    UString::Rep* rep = ident.ustring().rep();
420    if (!m_functions.contains(rep)) {
421        symbolTable().set(rep, m_nextParameterIndex);
422        RegisterID& parameter = registerFor(m_nextParameterIndex);
423        parameter.setIndex(m_nextParameterIndex);
424        result = &parameter;
425    }
426
427    // To maintain the calling convention, we have to allocate unique space for
428    // each parameter, even if the parameter doesn't make it into the symbol table.
429    ++m_nextParameterIndex;
430    ++m_codeBlock->m_numParameters;
431    return result;
432}
433
434RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
435{
436    if (ident == propertyNames().thisIdentifier)
437        return &m_thisRegister;
438
439    if (!shouldOptimizeLocals())
440        return 0;
441
442    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
443    if (entry.isNull())
444        return 0;
445
446    if (ident == propertyNames().arguments)
447        createArgumentsIfNecessary();
448
449    return &registerFor(entry.getIndex());
450}
451
452bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
453{
454    if (ident != propertyNames().arguments)
455        return false;
456
457    if (!shouldOptimizeLocals())
458        return false;
459
460    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
461    if (entry.isNull())
462        return false;
463
464    if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
465        return true;
466
467    return false;
468}
469
470RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
471{
472    ASSERT(willResolveToArguments(propertyNames().arguments));
473
474    SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.ustring().rep());
475    ASSERT(!entry.isNull());
476    return &registerFor(entry.getIndex());
477}
478
479RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
480{
481    if (m_codeType == EvalCode)
482        return 0;
483
484    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
485    if (entry.isNull())
486        return 0;
487
488    return &registerFor(entry.getIndex());
489}
490
491bool BytecodeGenerator::isLocal(const Identifier& ident)
492{
493    if (ident == propertyNames().thisIdentifier)
494        return true;
495
496    return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());
497}
498
499bool BytecodeGenerator::isLocalConstant(const Identifier& ident)
500{
501    return symbolTable().get(ident.ustring().rep()).isReadOnly();
502}
503
504RegisterID* BytecodeGenerator::newRegister()
505{
506    m_calleeRegisters.append(m_calleeRegisters.size());
507    m_codeBlock->m_numCalleeRegisters = max<int>(m_codeBlock->m_numCalleeRegisters, m_calleeRegisters.size());
508    return &m_calleeRegisters.last();
509}
510
511RegisterID* BytecodeGenerator::newTemporary()
512{
513    // Reclaim free register IDs.
514    while (m_calleeRegisters.size() && !m_calleeRegisters.last().refCount())
515        m_calleeRegisters.removeLast();
516
517    RegisterID* result = newRegister();
518    result->setTemporary();
519    return result;
520}
521
522RegisterID* BytecodeGenerator::highestUsedRegister()
523{
524    size_t count = m_codeBlock->m_numCalleeRegisters;
525    while (m_calleeRegisters.size() < count)
526        newRegister();
527    return &m_calleeRegisters.last();
528}
529
530PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, const Identifier* name)
531{
532    // Reclaim free label scopes.
533    while (m_labelScopes.size() && !m_labelScopes.last().refCount())
534        m_labelScopes.removeLast();
535
536    // Allocate new label scope.
537    LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
538    m_labelScopes.append(scope);
539    return &m_labelScopes.last();
540}
541
542PassRefPtr<Label> BytecodeGenerator::newLabel()
543{
544    // Reclaim free label IDs.
545    while (m_labels.size() && !m_labels.last().refCount())
546        m_labels.removeLast();
547
548    // Allocate new label ID.
549    m_labels.append(m_codeBlock);
550    return &m_labels.last();
551}
552
553PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
554{
555    unsigned newLabelIndex = instructions().size();
556    l0->setLocation(newLabelIndex);
557
558    if (m_codeBlock->numberOfJumpTargets()) {
559        unsigned lastLabelIndex = m_codeBlock->lastJumpTarget();
560        ASSERT(lastLabelIndex <= newLabelIndex);
561        if (newLabelIndex == lastLabelIndex) {
562            // Peephole optimizations have already been disabled by emitting the last label
563            return l0;
564        }
565    }
566
567    m_codeBlock->addJumpTarget(newLabelIndex);
568
569    // This disables peephole optimizations when an instruction is a jump target
570    m_lastOpcodeID = op_end;
571    return l0;
572}
573
574void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
575{
576    instructions().append(globalData()->interpreter->getOpcode(opcodeID));
577    m_lastOpcodeID = opcodeID;
578}
579
580void BytecodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
581{
582    ASSERT(instructions().size() >= 4);
583    size_t size = instructions().size();
584    dstIndex = instructions().at(size - 3).u.operand;
585    src1Index = instructions().at(size - 2).u.operand;
586    src2Index = instructions().at(size - 1).u.operand;
587}
588
589void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
590{
591    ASSERT(instructions().size() >= 3);
592    size_t size = instructions().size();
593    dstIndex = instructions().at(size - 2).u.operand;
594    srcIndex = instructions().at(size - 1).u.operand;
595}
596
597void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
598{
599    ASSERT(instructions().size() >= 4);
600    instructions().shrink(instructions().size() - 4);
601}
602
603void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
604{
605    ASSERT(instructions().size() >= 3);
606    instructions().shrink(instructions().size() - 3);
607}
608
609PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
610{
611    size_t begin = instructions().size();
612    emitOpcode(target->isForward() ? op_jmp : op_loop);
613    instructions().append(target->bind(begin, instructions().size()));
614    return target;
615}
616
617PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
618{
619    if (m_lastOpcodeID == op_less) {
620        int dstIndex;
621        int src1Index;
622        int src2Index;
623
624        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
625
626        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
627            rewindBinaryOp();
628
629            size_t begin = instructions().size();
630            emitOpcode(target->isForward() ? op_jless : op_loop_if_less);
631            instructions().append(src1Index);
632            instructions().append(src2Index);
633            instructions().append(target->bind(begin, instructions().size()));
634            return target;
635        }
636    } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {
637        int dstIndex;
638        int src1Index;
639        int src2Index;
640
641        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
642
643        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
644            rewindBinaryOp();
645
646            size_t begin = instructions().size();
647            emitOpcode(op_loop_if_lesseq);
648            instructions().append(src1Index);
649            instructions().append(src2Index);
650            instructions().append(target->bind(begin, instructions().size()));
651            return target;
652        }
653    } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
654        int dstIndex;
655        int srcIndex;
656
657        retrieveLastUnaryOp(dstIndex, srcIndex);
658
659        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
660            rewindUnaryOp();
661
662            size_t begin = instructions().size();
663            emitOpcode(op_jeq_null);
664            instructions().append(srcIndex);
665            instructions().append(target->bind(begin, instructions().size()));
666            return target;
667        }
668    } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
669        int dstIndex;
670        int srcIndex;
671
672        retrieveLastUnaryOp(dstIndex, srcIndex);
673
674        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
675            rewindUnaryOp();
676
677            size_t begin = instructions().size();
678            emitOpcode(op_jneq_null);
679            instructions().append(srcIndex);
680            instructions().append(target->bind(begin, instructions().size()));
681            return target;
682        }
683    }
684
685    size_t begin = instructions().size();
686
687    emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
688    instructions().append(cond->index());
689    instructions().append(target->bind(begin, instructions().size()));
690    return target;
691}
692
693PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
694{
695    if (m_lastOpcodeID == op_less && target->isForward()) {
696        int dstIndex;
697        int src1Index;
698        int src2Index;
699
700        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
701
702        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
703            rewindBinaryOp();
704
705            size_t begin = instructions().size();
706            emitOpcode(op_jnless);
707            instructions().append(src1Index);
708            instructions().append(src2Index);
709            instructions().append(target->bind(begin, instructions().size()));
710            return target;
711        }
712    } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
713        int dstIndex;
714        int src1Index;
715        int src2Index;
716
717        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
718
719        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
720            rewindBinaryOp();
721
722            size_t begin = instructions().size();
723            emitOpcode(op_jnlesseq);
724            instructions().append(src1Index);
725            instructions().append(src2Index);
726            instructions().append(target->bind(begin, instructions().size()));
727            return target;
728        }
729    } else if (m_lastOpcodeID == op_not) {
730        int dstIndex;
731        int srcIndex;
732
733        retrieveLastUnaryOp(dstIndex, srcIndex);
734
735        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
736            rewindUnaryOp();
737
738            size_t begin = instructions().size();
739            emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
740            instructions().append(srcIndex);
741            instructions().append(target->bind(begin, instructions().size()));
742            return target;
743        }
744    } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
745        int dstIndex;
746        int srcIndex;
747
748        retrieveLastUnaryOp(dstIndex, srcIndex);
749
750        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
751            rewindUnaryOp();
752
753            size_t begin = instructions().size();
754            emitOpcode(op_jneq_null);
755            instructions().append(srcIndex);
756            instructions().append(target->bind(begin, instructions().size()));
757            return target;
758        }
759    } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
760        int dstIndex;
761        int srcIndex;
762
763        retrieveLastUnaryOp(dstIndex, srcIndex);
764
765        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
766            rewindUnaryOp();
767
768            size_t begin = instructions().size();
769            emitOpcode(op_jeq_null);
770            instructions().append(srcIndex);
771            instructions().append(target->bind(begin, instructions().size()));
772            return target;
773        }
774    }
775
776    size_t begin = instructions().size();
777    emitOpcode(target->isForward() ? op_jfalse : op_loop_if_false);
778    instructions().append(cond->index());
779    instructions().append(target->bind(begin, instructions().size()));
780    return target;
781}
782
783PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
784{
785    size_t begin = instructions().size();
786
787    emitOpcode(op_jneq_ptr);
788    instructions().append(cond->index());
789    instructions().append(m_scopeChain->globalObject()->d()->callFunction);
790    instructions().append(target->bind(begin, instructions().size()));
791    return target;
792}
793
794PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
795{
796    size_t begin = instructions().size();
797
798    emitOpcode(op_jneq_ptr);
799    instructions().append(cond->index());
800    instructions().append(m_scopeChain->globalObject()->d()->applyFunction);
801    instructions().append(target->bind(begin, instructions().size()));
802    return target;
803}
804
805unsigned BytecodeGenerator::addConstant(const Identifier& ident)
806{
807    UString::Rep* rep = ident.ustring().rep();
808    pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
809    if (result.second) // new entry
810        m_codeBlock->addIdentifier(Identifier(m_globalData, rep));
811
812    return result.first->second;
813}
814
815RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
816{
817    int index = m_nextConstantOffset;
818
819    pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
820    if (result.second) {
821        m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
822        ++m_nextConstantOffset;
823        m_codeBlock->addConstantRegister(JSValue(v));
824    } else
825        index = result.first->second;
826
827    return &m_constantPoolRegisters[index];
828}
829
830unsigned BytecodeGenerator::addRegExp(RegExp* r)
831{
832    return m_codeBlock->addRegExp(r);
833}
834
835RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
836{
837    emitOpcode(op_mov);
838    instructions().append(dst->index());
839    instructions().append(src->index());
840    return dst;
841}
842
843RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src)
844{
845    emitOpcode(opcodeID);
846    instructions().append(dst->index());
847    instructions().append(src->index());
848    return dst;
849}
850
851RegisterID* BytecodeGenerator::emitPreInc(RegisterID* srcDst)
852{
853    emitOpcode(op_pre_inc);
854    instructions().append(srcDst->index());
855    return srcDst;
856}
857
858RegisterID* BytecodeGenerator::emitPreDec(RegisterID* srcDst)
859{
860    emitOpcode(op_pre_dec);
861    instructions().append(srcDst->index());
862    return srcDst;
863}
864
865RegisterID* BytecodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
866{
867    emitOpcode(op_post_inc);
868    instructions().append(dst->index());
869    instructions().append(srcDst->index());
870    return dst;
871}
872
873RegisterID* BytecodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
874{
875    emitOpcode(op_post_dec);
876    instructions().append(dst->index());
877    instructions().append(srcDst->index());
878    return dst;
879}
880
881RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes types)
882{
883    emitOpcode(opcodeID);
884    instructions().append(dst->index());
885    instructions().append(src1->index());
886    instructions().append(src2->index());
887
888    if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
889        opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
890        instructions().append(types.toInt());
891
892    return dst;
893}
894
895RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2)
896{
897    if (m_lastOpcodeID == op_typeof) {
898        int dstIndex;
899        int srcIndex;
900
901        retrieveLastUnaryOp(dstIndex, srcIndex);
902
903        if (src1->index() == dstIndex
904            && src1->isTemporary()
905            && m_codeBlock->isConstantRegisterIndex(src2->index())
906            && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
907            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->tryGetValue();
908            if (value == "undefined") {
909                rewindUnaryOp();
910                emitOpcode(op_is_undefined);
911                instructions().append(dst->index());
912                instructions().append(srcIndex);
913                return dst;
914            }
915            if (value == "boolean") {
916                rewindUnaryOp();
917                emitOpcode(op_is_boolean);
918                instructions().append(dst->index());
919                instructions().append(srcIndex);
920                return dst;
921            }
922            if (value == "number") {
923                rewindUnaryOp();
924                emitOpcode(op_is_number);
925                instructions().append(dst->index());
926                instructions().append(srcIndex);
927                return dst;
928            }
929            if (value == "string") {
930                rewindUnaryOp();
931                emitOpcode(op_is_string);
932                instructions().append(dst->index());
933                instructions().append(srcIndex);
934                return dst;
935            }
936            if (value == "object") {
937                rewindUnaryOp();
938                emitOpcode(op_is_object);
939                instructions().append(dst->index());
940                instructions().append(srcIndex);
941                return dst;
942            }
943            if (value == "function") {
944                rewindUnaryOp();
945                emitOpcode(op_is_function);
946                instructions().append(dst->index());
947                instructions().append(srcIndex);
948                return dst;
949            }
950        }
951    }
952
953    emitOpcode(opcodeID);
954    instructions().append(dst->index());
955    instructions().append(src1->index());
956    instructions().append(src2->index());
957    return dst;
958}
959
960RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
961{
962    return emitLoad(dst, jsBoolean(b));
963}
964
965RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
966{
967    // FIXME: Our hash tables won't hold infinity, so we make a new JSNumberCell each time.
968    // Later we can do the extra work to handle that like the other cases.
969    if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
970        return emitLoad(dst, jsNumber(globalData(), number));
971    JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second;
972    if (!valueInMap)
973        valueInMap = jsNumber(globalData(), number);
974    return emitLoad(dst, valueInMap);
975}
976
977RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
978{
979    JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second;
980    if (!stringInMap)
981        stringInMap = jsOwnedString(globalData(), identifier.ustring());
982    return emitLoad(dst, JSValue(stringInMap));
983}
984
985RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
986{
987    RegisterID* constantID = addConstantValue(v);
988    if (dst)
989        return emitMove(dst, constantID);
990    return constantID;
991}
992
993bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject)
994{
995    // Cases where we cannot statically optimize the lookup.
996    if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
997        stackDepth = 0;
998        index = missingSymbolMarker();
999
1000        if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
1001            ScopeChainIterator iter = m_scopeChain->begin();
1002            globalObject = *iter;
1003            ASSERT((++iter) == m_scopeChain->end());
1004        }
1005        return false;
1006    }
1007
1008    size_t depth = 0;
1009
1010    ScopeChainIterator iter = m_scopeChain->begin();
1011    ScopeChainIterator end = m_scopeChain->end();
1012    for (; iter != end; ++iter, ++depth) {
1013        JSObject* currentScope = *iter;
1014        if (!currentScope->isVariableObject())
1015            break;
1016        JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
1017        SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.ustring().rep());
1018
1019        // Found the property
1020        if (!entry.isNull()) {
1021            if (entry.isReadOnly() && forWriting) {
1022                stackDepth = 0;
1023                index = missingSymbolMarker();
1024                if (++iter == end)
1025                    globalObject = currentVariableObject;
1026                return false;
1027            }
1028            stackDepth = depth;
1029            index = entry.getIndex();
1030            if (++iter == end)
1031                globalObject = currentVariableObject;
1032            return true;
1033        }
1034        if (currentVariableObject->isDynamicScope())
1035            break;
1036    }
1037
1038    // Can't locate the property but we're able to avoid a few lookups.
1039    stackDepth = depth;
1040    index = missingSymbolMarker();
1041    JSObject* scope = *iter;
1042    if (++iter == end)
1043        globalObject = scope;
1044    return true;
1045}
1046
1047RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
1048{
1049    emitOpcode(op_instanceof);
1050    instructions().append(dst->index());
1051    instructions().append(value->index());
1052    instructions().append(base->index());
1053    instructions().append(basePrototype->index());
1054    return dst;
1055}
1056
1057RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
1058{
1059    size_t depth = 0;
1060    int index = 0;
1061    JSObject* globalObject = 0;
1062    if (!findScopedProperty(property, index, depth, false, globalObject) && !globalObject) {
1063        // We can't optimise at all :-(
1064        emitOpcode(op_resolve);
1065        instructions().append(dst->index());
1066        instructions().append(addConstant(property));
1067        return dst;
1068    }
1069
1070    if (globalObject) {
1071        bool forceGlobalResolve = false;
1072        if (m_regeneratingForExceptionInfo) {
1073#if ENABLE(JIT)
1074            forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());
1075#else
1076            forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());
1077#endif
1078        }
1079
1080        if (index != missingSymbolMarker() && !forceGlobalResolve) {
1081            // Directly index the property lookup across multiple scopes.
1082            return emitGetScopedVar(dst, depth, index, globalObject);
1083        }
1084
1085#if ENABLE(JIT)
1086        m_codeBlock->addGlobalResolveInfo(instructions().size());
1087#else
1088        m_codeBlock->addGlobalResolveInstruction(instructions().size());
1089#endif
1090        emitOpcode(op_resolve_global);
1091        instructions().append(dst->index());
1092        instructions().append(globalObject);
1093        instructions().append(addConstant(property));
1094        instructions().append(0);
1095        instructions().append(0);
1096        return dst;
1097    }
1098
1099    if (index != missingSymbolMarker()) {
1100        // Directly index the property lookup across multiple scopes.
1101        return emitGetScopedVar(dst, depth, index, globalObject);
1102    }
1103
1104    // In this case we are at least able to drop a few scope chains from the
1105    // lookup chain, although we still need to hash from then on.
1106    emitOpcode(op_resolve_skip);
1107    instructions().append(dst->index());
1108    instructions().append(addConstant(property));
1109    instructions().append(depth);
1110    return dst;
1111}
1112
1113RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
1114{
1115    if (globalObject) {
1116        emitOpcode(op_get_global_var);
1117        instructions().append(dst->index());
1118        instructions().append(asCell(globalObject));
1119        instructions().append(index);
1120        return dst;
1121    }
1122
1123    emitOpcode(op_get_scoped_var);
1124    instructions().append(dst->index());
1125    instructions().append(index);
1126    instructions().append(depth);
1127    return dst;
1128}
1129
1130RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue globalObject)
1131{
1132    if (globalObject) {
1133        emitOpcode(op_put_global_var);
1134        instructions().append(asCell(globalObject));
1135        instructions().append(index);
1136        instructions().append(value->index());
1137        return value;
1138    }
1139    emitOpcode(op_put_scoped_var);
1140    instructions().append(index);
1141    instructions().append(depth);
1142    instructions().append(value->index());
1143    return value;
1144}
1145
1146RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
1147{
1148    size_t depth = 0;
1149    int index = 0;
1150    JSObject* globalObject = 0;
1151    findScopedProperty(property, index, depth, false, globalObject);
1152    if (!globalObject) {
1153        // We can't optimise at all :-(
1154        emitOpcode(op_resolve_base);
1155        instructions().append(dst->index());
1156        instructions().append(addConstant(property));
1157        return dst;
1158    }
1159
1160    // Global object is the base
1161    return emitLoad(dst, JSValue(globalObject));
1162}
1163
1164RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
1165{
1166    size_t depth = 0;
1167    int index = 0;
1168    JSObject* globalObject = 0;
1169    if (!findScopedProperty(property, index, depth, false, globalObject) || !globalObject) {
1170        // We can't optimise at all :-(
1171        emitOpcode(op_resolve_with_base);
1172        instructions().append(baseDst->index());
1173        instructions().append(propDst->index());
1174        instructions().append(addConstant(property));
1175        return baseDst;
1176    }
1177
1178    bool forceGlobalResolve = false;
1179    if (m_regeneratingForExceptionInfo) {
1180#if ENABLE(JIT)
1181        forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());
1182#else
1183        forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());
1184#endif
1185    }
1186
1187    // Global object is the base
1188    emitLoad(baseDst, JSValue(globalObject));
1189
1190    if (index != missingSymbolMarker() && !forceGlobalResolve) {
1191        // Directly index the property lookup across multiple scopes.
1192        emitGetScopedVar(propDst, depth, index, globalObject);
1193        return baseDst;
1194    }
1195
1196#if ENABLE(JIT)
1197    m_codeBlock->addGlobalResolveInfo(instructions().size());
1198#else
1199    m_codeBlock->addGlobalResolveInstruction(instructions().size());
1200#endif
1201    emitOpcode(op_resolve_global);
1202    instructions().append(propDst->index());
1203    instructions().append(globalObject);
1204    instructions().append(addConstant(property));
1205    instructions().append(0);
1206    instructions().append(0);
1207    return baseDst;
1208}
1209
1210void BytecodeGenerator::emitMethodCheck()
1211{
1212    emitOpcode(op_method_check);
1213}
1214
1215RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
1216{
1217#if ENABLE(JIT)
1218    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
1219#else
1220    m_codeBlock->addPropertyAccessInstruction(instructions().size());
1221#endif
1222
1223    emitOpcode(op_get_by_id);
1224    instructions().append(dst->index());
1225    instructions().append(base->index());
1226    instructions().append(addConstant(property));
1227    instructions().append(0);
1228    instructions().append(0);
1229    instructions().append(0);
1230    instructions().append(0);
1231    return dst;
1232}
1233
1234RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
1235{
1236#if ENABLE(JIT)
1237    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
1238#else
1239    m_codeBlock->addPropertyAccessInstruction(instructions().size());
1240#endif
1241
1242    emitOpcode(op_put_by_id);
1243    instructions().append(base->index());
1244    instructions().append(addConstant(property));
1245    instructions().append(value->index());
1246    instructions().append(0);
1247    instructions().append(0);
1248    instructions().append(0);
1249    instructions().append(0);
1250    return value;
1251}
1252
1253RegisterID* BytecodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
1254{
1255    emitOpcode(op_put_getter);
1256    instructions().append(base->index());
1257    instructions().append(addConstant(property));
1258    instructions().append(value->index());
1259    return value;
1260}
1261
1262RegisterID* BytecodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
1263{
1264    emitOpcode(op_put_setter);
1265    instructions().append(base->index());
1266    instructions().append(addConstant(property));
1267    instructions().append(value->index());
1268    return value;
1269}
1270
1271RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
1272{
1273    emitOpcode(op_del_by_id);
1274    instructions().append(dst->index());
1275    instructions().append(base->index());
1276    instructions().append(addConstant(property));
1277    return dst;
1278}
1279
1280RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1281{
1282    for (size_t i = m_forInContextStack.size(); i > 0; i--) {
1283        ForInContext& context = m_forInContextStack[i - 1];
1284        if (context.propertyRegister == property) {
1285            emitOpcode(op_get_by_pname);
1286            instructions().append(dst->index());
1287            instructions().append(base->index());
1288            instructions().append(property->index());
1289            instructions().append(context.expectedSubscriptRegister->index());
1290            instructions().append(context.iterRegister->index());
1291            instructions().append(context.indexRegister->index());
1292            return dst;
1293        }
1294    }
1295    emitOpcode(op_get_by_val);
1296    instructions().append(dst->index());
1297    instructions().append(base->index());
1298    instructions().append(property->index());
1299    return dst;
1300}
1301
1302RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
1303{
1304    emitOpcode(op_put_by_val);
1305    instructions().append(base->index());
1306    instructions().append(property->index());
1307    instructions().append(value->index());
1308    return value;
1309}
1310
1311RegisterID* BytecodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
1312{
1313    emitOpcode(op_del_by_val);
1314    instructions().append(dst->index());
1315    instructions().append(base->index());
1316    instructions().append(property->index());
1317    return dst;
1318}
1319
1320RegisterID* BytecodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
1321{
1322    emitOpcode(op_put_by_index);
1323    instructions().append(base->index());
1324    instructions().append(index);
1325    instructions().append(value->index());
1326    return value;
1327}
1328
1329RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
1330{
1331    emitOpcode(op_new_object);
1332    instructions().append(dst->index());
1333    return dst;
1334}
1335
1336RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements)
1337{
1338    Vector<RefPtr<RegisterID>, 16> argv;
1339    for (ElementNode* n = elements; n; n = n->next()) {
1340        if (n->elision())
1341            break;
1342        argv.append(newTemporary());
1343        // op_new_array requires the initial values to be a sequential range of registers
1344        ASSERT(argv.size() == 1 || argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
1345        emitNode(argv.last().get(), n->value());
1346    }
1347    emitOpcode(op_new_array);
1348    instructions().append(dst->index());
1349    instructions().append(argv.size() ? argv[0]->index() : 0); // argv
1350    instructions().append(argv.size()); // argc
1351    return dst;
1352}
1353
1354RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
1355{
1356    unsigned index = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
1357
1358    emitOpcode(op_new_func);
1359    instructions().append(dst->index());
1360    instructions().append(index);
1361    return dst;
1362}
1363
1364RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
1365{
1366    emitOpcode(op_new_regexp);
1367    instructions().append(dst->index());
1368    instructions().append(addRegExp(regExp));
1369    return dst;
1370}
1371
1372
1373RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
1374{
1375    FunctionBodyNode* function = n->body();
1376    unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
1377
1378    emitOpcode(op_new_func_exp);
1379    instructions().append(r0->index());
1380    instructions().append(index);
1381    return r0;
1382}
1383
1384RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1385{
1386    return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
1387}
1388
1389void BytecodeGenerator::createArgumentsIfNecessary()
1390{
1391    if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
1392        emitOpcode(op_create_arguments);
1393}
1394
1395RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1396{
1397    createArgumentsIfNecessary();
1398    return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
1399}
1400
1401RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1402{
1403    ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
1404    ASSERT(func->refCount());
1405    ASSERT(thisRegister->refCount());
1406
1407    RegisterID* originalFunc = func;
1408    if (m_shouldEmitProfileHooks) {
1409        // If codegen decided to recycle func as this call's destination register,
1410        // we need to undo that optimization here so that func will still be around
1411        // for the sake of op_profile_did_call.
1412        if (dst == func) {
1413            RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister);
1414            RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func);
1415
1416            thisRegister = movedThisRegister.release().releaseRef();
1417            func = movedFunc.release().releaseRef();
1418        }
1419    }
1420
1421    // Generate code for arguments.
1422    Vector<RefPtr<RegisterID>, 16> argv;
1423    argv.append(thisRegister);
1424    for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) {
1425        argv.append(newTemporary());
1426        // op_call requires the arguments to be a sequential range of registers
1427        ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
1428        emitNode(argv.last().get(), n);
1429    }
1430
1431    // Reserve space for call frame.
1432    Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1433    for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1434        callFrame.append(newTemporary());
1435
1436    if (m_shouldEmitProfileHooks) {
1437        emitOpcode(op_profile_will_call);
1438        instructions().append(func->index());
1439
1440#if ENABLE(JIT)
1441        m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index());
1442#endif
1443    }
1444
1445    emitExpressionInfo(divot, startOffset, endOffset);
1446
1447#if ENABLE(JIT)
1448    m_codeBlock->addCallLinkInfo();
1449#endif
1450
1451    // Emit call.
1452    emitOpcode(opcodeID);
1453    instructions().append(dst->index()); // dst
1454    instructions().append(func->index()); // func
1455    instructions().append(argv.size()); // argCount
1456    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
1457
1458    if (m_shouldEmitProfileHooks) {
1459        emitOpcode(op_profile_did_call);
1460        instructions().append(func->index());
1461
1462        if (dst == originalFunc) {
1463            thisRegister->deref();
1464            func->deref();
1465        }
1466    }
1467
1468    return dst;
1469}
1470
1471RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* arguments)
1472{
1473    ASSERT(argCountDst->index() < arguments->index());
1474    emitOpcode(op_load_varargs);
1475    instructions().append(argCountDst->index());
1476    instructions().append(arguments->index());
1477    return argCountDst;
1478}
1479
1480RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCountRegister, unsigned divot, unsigned startOffset, unsigned endOffset)
1481{
1482    ASSERT(func->refCount());
1483    ASSERT(thisRegister->refCount());
1484    ASSERT(dst != func);
1485    if (m_shouldEmitProfileHooks) {
1486        emitOpcode(op_profile_will_call);
1487        instructions().append(func->index());
1488
1489#if ENABLE(JIT)
1490        m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index());
1491#endif
1492    }
1493
1494    emitExpressionInfo(divot, startOffset, endOffset);
1495
1496    // Emit call.
1497    emitOpcode(op_call_varargs);
1498    instructions().append(dst->index()); // dst
1499    instructions().append(func->index()); // func
1500    instructions().append(argCountRegister->index()); // arg count
1501    instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
1502    if (m_shouldEmitProfileHooks) {
1503        emitOpcode(op_profile_did_call);
1504        instructions().append(func->index());
1505    }
1506    return dst;
1507}
1508
1509RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
1510{
1511    if (m_codeBlock->needsFullScopeChain()) {
1512        emitOpcode(op_tear_off_activation);
1513        instructions().append(m_activationRegisterIndex);
1514    } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1)
1515        emitOpcode(op_tear_off_arguments);
1516
1517    return emitUnaryNoDstOp(op_ret, src);
1518}
1519
1520RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* src)
1521{
1522    emitOpcode(opcodeID);
1523    instructions().append(src->index());
1524    return src;
1525}
1526
1527RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
1528{
1529    ASSERT(func->refCount());
1530
1531    RegisterID* originalFunc = func;
1532    if (m_shouldEmitProfileHooks) {
1533        // If codegen decided to recycle func as this call's destination register,
1534        // we need to undo that optimization here so that func will still be around
1535        // for the sake of op_profile_did_call.
1536        if (dst == func) {
1537            RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func);
1538            func = movedFunc.release().releaseRef();
1539        }
1540    }
1541
1542    RefPtr<RegisterID> funcProto = newTemporary();
1543
1544    // Generate code for arguments.
1545    Vector<RefPtr<RegisterID>, 16> argv;
1546    argv.append(newTemporary()); // reserve space for "this"
1547    for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode : 0; n; n = n->m_next) {
1548        argv.append(newTemporary());
1549        // op_construct requires the arguments to be a sequential range of registers
1550        ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
1551        emitNode(argv.last().get(), n);
1552    }
1553
1554    if (m_shouldEmitProfileHooks) {
1555        emitOpcode(op_profile_will_call);
1556        instructions().append(func->index());
1557    }
1558
1559    // Load prototype.
1560    emitExpressionInfo(divot, startOffset, endOffset);
1561    emitGetByIdExceptionInfo(op_construct);
1562    emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype);
1563
1564    // Reserve space for call frame.
1565    Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
1566    for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
1567        callFrame.append(newTemporary());
1568
1569    emitExpressionInfo(divot, startOffset, endOffset);
1570
1571#if ENABLE(JIT)
1572    m_codeBlock->addCallLinkInfo();
1573#endif
1574
1575    emitOpcode(op_construct);
1576    instructions().append(dst->index()); // dst
1577    instructions().append(func->index()); // func
1578    instructions().append(argv.size()); // argCount
1579    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
1580    instructions().append(funcProto->index()); // proto
1581    instructions().append(argv[0]->index()); // thisRegister
1582
1583    emitOpcode(op_construct_verify);
1584    instructions().append(dst->index());
1585    instructions().append(argv[0]->index());
1586
1587    if (m_shouldEmitProfileHooks) {
1588        emitOpcode(op_profile_did_call);
1589        instructions().append(func->index());
1590
1591        if (dst == originalFunc)
1592            func->deref();
1593    }
1594
1595    return dst;
1596}
1597
1598RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
1599{
1600    emitOpcode(op_strcat);
1601    instructions().append(dst->index());
1602    instructions().append(src->index());
1603    instructions().append(count);
1604
1605    return dst;
1606}
1607
1608void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
1609{
1610    emitOpcode(op_to_primitive);
1611    instructions().append(dst->index());
1612    instructions().append(src->index());
1613}
1614
1615RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
1616{
1617    ASSERT(scope->isTemporary());
1618    ControlFlowContext context;
1619    context.isFinallyBlock = false;
1620    m_scopeContextStack.append(context);
1621    m_dynamicScopeDepth++;
1622    createArgumentsIfNecessary();
1623
1624    return emitUnaryNoDstOp(op_push_scope, scope);
1625}
1626
1627void BytecodeGenerator::emitPopScope()
1628{
1629    ASSERT(m_scopeContextStack.size());
1630    ASSERT(!m_scopeContextStack.last().isFinallyBlock);
1631
1632    emitOpcode(op_pop_scope);
1633
1634    m_scopeContextStack.removeLast();
1635    m_dynamicScopeDepth--;
1636}
1637
1638void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine)
1639{
1640    if (!m_shouldEmitDebugHooks)
1641        return;
1642    emitOpcode(op_debug);
1643    instructions().append(debugHookID);
1644    instructions().append(firstLine);
1645    instructions().append(lastLine);
1646}
1647
1648void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst)
1649{
1650    ControlFlowContext scope;
1651    scope.isFinallyBlock = true;
1652    FinallyContext context = { target, retAddrDst };
1653    scope.finallyContext = context;
1654    m_scopeContextStack.append(scope);
1655    m_finallyDepth++;
1656}
1657
1658void BytecodeGenerator::popFinallyContext()
1659{
1660    ASSERT(m_scopeContextStack.size());
1661    ASSERT(m_scopeContextStack.last().isFinallyBlock);
1662    ASSERT(m_finallyDepth > 0);
1663    m_scopeContextStack.removeLast();
1664    m_finallyDepth--;
1665}
1666
1667LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
1668{
1669    // Reclaim free label scopes.
1670    //
1671    // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
1672    // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
1673    // size 0, leading to segfaulty badness.  We are yet to identify a valid cause within our code to
1674    // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
1675    // loop condition is a workaround.
1676    while (m_labelScopes.size()) {
1677        if  (m_labelScopes.last().refCount())
1678            break;
1679        m_labelScopes.removeLast();
1680    }
1681
1682    if (!m_labelScopes.size())
1683        return 0;
1684
1685    // We special-case the following, which is a syntax error in Firefox:
1686    // label:
1687    //     break;
1688    if (name.isEmpty()) {
1689        for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1690            LabelScope* scope = &m_labelScopes[i];
1691            if (scope->type() != LabelScope::NamedLabel) {
1692                ASSERT(scope->breakTarget());
1693                return scope;
1694            }
1695        }
1696        return 0;
1697    }
1698
1699    for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1700        LabelScope* scope = &m_labelScopes[i];
1701        if (scope->name() && *scope->name() == name) {
1702            ASSERT(scope->breakTarget());
1703            return scope;
1704        }
1705    }
1706    return 0;
1707}
1708
1709LabelScope* BytecodeGenerator::continueTarget(const Identifier& name)
1710{
1711    // Reclaim free label scopes.
1712    while (m_labelScopes.size() && !m_labelScopes.last().refCount())
1713        m_labelScopes.removeLast();
1714
1715    if (!m_labelScopes.size())
1716        return 0;
1717
1718    if (name.isEmpty()) {
1719        for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1720            LabelScope* scope = &m_labelScopes[i];
1721            if (scope->type() == LabelScope::Loop) {
1722                ASSERT(scope->continueTarget());
1723                return scope;
1724            }
1725        }
1726        return 0;
1727    }
1728
1729    // Continue to the loop nested nearest to the label scope that matches
1730    // 'name'.
1731    LabelScope* result = 0;
1732    for (int i = m_labelScopes.size() - 1; i >= 0; --i) {
1733        LabelScope* scope = &m_labelScopes[i];
1734        if (scope->type() == LabelScope::Loop) {
1735            ASSERT(scope->continueTarget());
1736            result = scope;
1737        }
1738        if (scope->name() && *scope->name() == name)
1739            return result; // may be 0
1740    }
1741    return 0;
1742}
1743
1744PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope)
1745{
1746    while (topScope > bottomScope) {
1747        // First we count the number of dynamic scopes we need to remove to get
1748        // to a finally block.
1749        int nNormalScopes = 0;
1750        while (topScope > bottomScope) {
1751            if (topScope->isFinallyBlock)
1752                break;
1753            ++nNormalScopes;
1754            --topScope;
1755        }
1756
1757        if (nNormalScopes) {
1758            size_t begin = instructions().size();
1759
1760            // We need to remove a number of dynamic scopes to get to the next
1761            // finally block
1762            emitOpcode(op_jmp_scopes);
1763            instructions().append(nNormalScopes);
1764
1765            // If topScope == bottomScope then there isn't actually a finally block
1766            // left to emit, so make the jmp_scopes jump directly to the target label
1767            if (topScope == bottomScope) {
1768                instructions().append(target->bind(begin, instructions().size()));
1769                return target;
1770            }
1771
1772            // Otherwise we just use jmp_scopes to pop a group of scopes and go
1773            // to the next instruction
1774            RefPtr<Label> nextInsn = newLabel();
1775            instructions().append(nextInsn->bind(begin, instructions().size()));
1776            emitLabel(nextInsn.get());
1777        }
1778
1779        while (topScope > bottomScope && topScope->isFinallyBlock) {
1780            emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
1781            --topScope;
1782        }
1783    }
1784    return emitJump(target);
1785}
1786
1787PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetScopeDepth)
1788{
1789    ASSERT(scopeDepth() - targetScopeDepth >= 0);
1790    ASSERT(target->isForward());
1791
1792    size_t scopeDelta = scopeDepth() - targetScopeDepth;
1793    ASSERT(scopeDelta <= m_scopeContextStack.size());
1794    if (!scopeDelta)
1795        return emitJump(target);
1796
1797    if (m_finallyDepth)
1798        return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
1799
1800    size_t begin = instructions().size();
1801
1802    emitOpcode(op_jmp_scopes);
1803    instructions().append(scopeDelta);
1804    instructions().append(target->bind(begin, instructions().size()));
1805    return target;
1806}
1807
1808RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget)
1809{
1810    size_t begin = instructions().size();
1811
1812    emitOpcode(op_get_pnames);
1813    instructions().append(dst->index());
1814    instructions().append(base->index());
1815    instructions().append(i->index());
1816    instructions().append(size->index());
1817    instructions().append(breakTarget->bind(begin, instructions().size()));
1818    return dst;
1819}
1820
1821RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target)
1822{
1823    size_t begin = instructions().size();
1824
1825    emitOpcode(op_next_pname);
1826    instructions().append(dst->index());
1827    instructions().append(base->index());
1828    instructions().append(i->index());
1829    instructions().append(size->index());
1830    instructions().append(iter->index());
1831    instructions().append(target->bind(begin, instructions().size()));
1832    return dst;
1833}
1834
1835RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
1836{
1837#if ENABLE(JIT)
1838    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
1839#else
1840    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
1841#endif
1842
1843    m_codeBlock->addExceptionHandler(info);
1844    emitOpcode(op_catch);
1845    instructions().append(targetRegister->index());
1846    return targetRegister;
1847}
1848
1849RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue message)
1850{
1851    emitOpcode(op_new_error);
1852    instructions().append(dst->index());
1853    instructions().append(static_cast<int>(type));
1854    instructions().append(addConstantValue(message)->index());
1855    return dst;
1856}
1857
1858PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
1859{
1860    size_t begin = instructions().size();
1861
1862    emitOpcode(op_jsr);
1863    instructions().append(retAddrDst->index());
1864    instructions().append(finally->bind(begin, instructions().size()));
1865    emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
1866    return finally;
1867}
1868
1869void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
1870{
1871    emitOpcode(op_sret);
1872    instructions().append(retAddrSrc->index());
1873}
1874
1875void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
1876{
1877    ControlFlowContext context;
1878    context.isFinallyBlock = false;
1879    m_scopeContextStack.append(context);
1880    m_dynamicScopeDepth++;
1881
1882    createArgumentsIfNecessary();
1883
1884    emitOpcode(op_push_new_scope);
1885    instructions().append(dst->index());
1886    instructions().append(addConstant(property));
1887    instructions().append(value->index());
1888}
1889
1890void BytecodeGenerator::beginSwitch(RegisterID* scrutineeRegister, SwitchInfo::SwitchType type)
1891{
1892    SwitchInfo info = { instructions().size(), type };
1893    switch (type) {
1894        case SwitchInfo::SwitchImmediate:
1895            emitOpcode(op_switch_imm);
1896            break;
1897        case SwitchInfo::SwitchCharacter:
1898            emitOpcode(op_switch_char);
1899            break;
1900        case SwitchInfo::SwitchString:
1901            emitOpcode(op_switch_string);
1902            break;
1903        default:
1904            ASSERT_NOT_REACHED();
1905    }
1906
1907    instructions().append(0); // place holder for table index
1908    instructions().append(0); // place holder for default target
1909    instructions().append(scrutineeRegister->index());
1910    m_switchContextStack.append(info);
1911}
1912
1913static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t max)
1914{
1915    UNUSED_PARAM(max);
1916    ASSERT(node->isNumber());
1917    double value = static_cast<NumberNode*>(node)->value();
1918    int32_t key = static_cast<int32_t>(value);
1919    ASSERT(key == value);
1920    ASSERT(key >= min);
1921    ASSERT(key <= max);
1922    return key - min;
1923}
1924
1925static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1926{
1927    jumpTable.min = min;
1928    jumpTable.branchOffsets.resize(max - min + 1);
1929    jumpTable.branchOffsets.fill(0);
1930    for (uint32_t i = 0; i < clauseCount; ++i) {
1931        // We're emitting this after the clause labels should have been fixed, so
1932        // the labels should not be "forward" references
1933        ASSERT(!labels[i]->isForward());
1934        jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3));
1935    }
1936}
1937
1938static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t max)
1939{
1940    UNUSED_PARAM(max);
1941    ASSERT(node->isString());
1942    UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep();
1943    ASSERT(clause->size() == 1);
1944
1945    int32_t key = clause->data()[0];
1946    ASSERT(key >= min);
1947    ASSERT(key <= max);
1948    return key - min;
1949}
1950
1951static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, int32_t min, int32_t max)
1952{
1953    jumpTable.min = min;
1954    jumpTable.branchOffsets.resize(max - min + 1);
1955    jumpTable.branchOffsets.fill(0);
1956    for (uint32_t i = 0; i < clauseCount; ++i) {
1957        // We're emitting this after the clause labels should have been fixed, so
1958        // the labels should not be "forward" references
1959        ASSERT(!labels[i]->isForward());
1960        jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3));
1961    }
1962}
1963
1964static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t switchAddress, uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes)
1965{
1966    for (uint32_t i = 0; i < clauseCount; ++i) {
1967        // We're emitting this after the clause labels should have been fixed, so
1968        // the labels should not be "forward" references
1969        ASSERT(!labels[i]->isForward());
1970
1971        ASSERT(nodes[i]->isString());
1972        UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
1973        OffsetLocation location;
1974        location.branchOffset = labels[i]->bind(switchAddress, switchAddress + 3);
1975        jumpTable.offsetTable.add(clause, location);
1976    }
1977}
1978
1979void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, ExpressionNode** nodes, Label* defaultLabel, int32_t min, int32_t max)
1980{
1981    SwitchInfo switchInfo = m_switchContextStack.last();
1982    m_switchContextStack.removeLast();
1983    if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
1984        instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
1985        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
1986
1987        SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
1988        prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
1989    } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
1990        instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
1991        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
1992
1993        SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
1994        prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
1995    } else {
1996        ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
1997        instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
1998        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
1999
2000        StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
2001        prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
2002    }
2003}
2004
2005RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
2006{
2007    // It would be nice to do an even better job of identifying exactly where the expression is.
2008    // And we could make the caller pass the node pointer in, if there was some way of getting
2009    // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
2010    // is still good enough to get us an accurate line number.
2011    emitExpressionInfo(0, 0, 0);
2012    RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep"));
2013    emitThrow(exception);
2014    return exception;
2015}
2016
2017} // namespace JSC
2018