1/*
2*  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3*  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4*  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
5*  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6*  Copyright (C) 2007 Maks Orlovich
7*  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2012 Igalia, S.L.
9*
10*  This library is free software; you can redistribute it and/or
11*  modify it under the terms of the GNU Library General Public
12*  License as published by the Free Software Foundation; either
13*  version 2 of the License, or (at your option) any later version.
14*
15*  This library is distributed in the hope that it will be useful,
16*  but WITHOUT ANY WARRANTY; without even the implied warranty of
17*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18*  Library General Public License for more details.
19*
20*  You should have received a copy of the GNU Library General Public License
21*  along with this library; see the file COPYING.LIB.  If not, write to
22*  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23*  Boston, MA 02110-1301, USA.
24*
25*/
26
27#include "config.h"
28#include "Nodes.h"
29#include "NodeConstructors.h"
30
31#include "BuiltinNames.h"
32#include "BytecodeGenerator.h"
33#include "CallFrame.h"
34#include "Debugger.h"
35#include "JIT.h"
36#include "JSFunction.h"
37#include "JSGlobalObject.h"
38#include "JSNameScope.h"
39#include "JSONObject.h"
40#include "LabelScope.h"
41#include "Lexer.h"
42#include "JSCInlines.h"
43#include "Parser.h"
44#include "PropertyNameArray.h"
45#include "RegExpCache.h"
46#include "RegExpObject.h"
47#include "SamplingTool.h"
48#include "StackAlignment.h"
49#include <wtf/Assertions.h>
50#include <wtf/RefCountedLeakCounter.h>
51#include <wtf/Threading.h>
52
53using namespace WTF;
54
55namespace JSC {
56
57/*
58    Details of the emitBytecode function.
59
60    Return value: The register holding the production's value.
61             dst: An optional parameter specifying the most efficient destination at
62                  which to store the production's value. The callee must honor dst.
63
64    The dst argument provides for a crude form of copy propagation. For example,
65
66        x = 1
67
68    becomes
69
70        load r[x], 1
71
72    instead of
73
74        load r0, 1
75        mov r[x], r0
76
77    because the assignment node, "x =", passes r[x] as dst to the number node, "1".
78*/
79
80void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
81{
82    RegisterID* result = generator.emitNode(this);
83    if (fallThroughMode == FallThroughMeansTrue)
84        generator.emitJumpIfFalse(result, falseTarget);
85    else
86        generator.emitJumpIfTrue(result, trueTarget);
87}
88
89// ------------------------------ ThrowableExpressionData --------------------------------
90
91RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
92{
93    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
94    generator.emitThrowReferenceError(message);
95    return generator.newTemporary();
96}
97
98// ------------------------------ ConstantNode ----------------------------------
99
100void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
101{
102    TriState value = jsValue(generator).pureToBoolean();
103    if (value == MixedTriState)
104        ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
105    else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
106        generator.emitJump(trueTarget);
107    else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
108        generator.emitJump(falseTarget);
109
110    // All other cases are unconditional fall-throughs, like "if (true)".
111}
112
113RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
114{
115    if (dst == generator.ignoredResult())
116        return 0;
117    return generator.emitLoad(dst, jsValue(generator));
118}
119
120JSValue StringNode::jsValue(BytecodeGenerator& generator) const
121{
122    return generator.addStringConstant(m_value);
123}
124
125// ------------------------------ RegExpNode -----------------------------------
126
127RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
128{
129    if (dst == generator.ignoredResult())
130        return 0;
131    return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string())));
132}
133
134// ------------------------------ ThisNode -------------------------------------
135
136RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
137{
138    if (dst == generator.ignoredResult())
139        return 0;
140    return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
141}
142
143// ------------------------------ ResolveNode ----------------------------------
144
145bool ResolveNode::isPure(BytecodeGenerator& generator) const
146{
147    return generator.local(m_ident).get();
148}
149
150RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
151{
152    if (Local local = generator.local(m_ident)) {
153        if (dst == generator.ignoredResult())
154            return 0;
155        return generator.moveToDestinationIfNeeded(dst, local.get());
156    }
157
158    JSTextPosition divot = m_start + m_ident.length();
159    generator.emitExpressionInfo(divot, m_start, divot);
160    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
161    return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound);
162}
163
164// ------------------------------ ArrayNode ------------------------------------
165
166RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
167{
168    // FIXME: Should we put all of this code into emitNewArray?
169
170    unsigned length = 0;
171    ElementNode* firstPutElement;
172    for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
173        if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
174            break;
175        ++length;
176    }
177
178    if (!firstPutElement && !m_elision)
179        return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
180
181    RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
182    ElementNode* n = firstPutElement;
183    for (; n; n = n->next()) {
184        if (n->value()->isSpreadExpression())
185            goto handleSpread;
186        RegisterID* value = generator.emitNode(n->value());
187        length += n->elision();
188        generator.emitPutByIndex(array.get(), length++, value);
189    }
190
191    if (m_elision) {
192        RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
193        generator.emitPutById(array.get(), generator.propertyNames().length, value);
194    }
195
196    return generator.moveToDestinationIfNeeded(dst, array.get());
197
198handleSpread:
199    RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
200    auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
201    {
202        generator.emitDirectPutByVal(array.get(), index.get(), value);
203        generator.emitInc(index.get());
204    };
205    for (; n; n = n->next()) {
206        if (n->elision())
207            generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
208        if (n->value()->isSpreadExpression()) {
209            SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
210            generator.emitEnumeration(spread, spread->expression(), spreader);
211        } else {
212            generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
213            generator.emitInc(index.get());
214        }
215    }
216
217    if (m_elision) {
218        generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
219        generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
220    }
221    return generator.moveToDestinationIfNeeded(dst, array.get());
222}
223
224bool ArrayNode::isSimpleArray() const
225{
226    if (m_elision || m_optional)
227        return false;
228    for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
229        if (ptr->elision())
230            return false;
231    }
232    return true;
233}
234
235ArgumentListNode* ArrayNode::toArgumentList(VM* vm, int lineNumber, int startPosition) const
236{
237    ASSERT(!m_elision && !m_optional);
238    ElementNode* ptr = m_element;
239    if (!ptr)
240        return 0;
241    JSTokenLocation location;
242    location.line = lineNumber;
243    location.startOffset = startPosition;
244    ArgumentListNode* head = new (vm) ArgumentListNode(location, ptr->value());
245    ArgumentListNode* tail = head;
246    ptr = ptr->next();
247    for (; ptr; ptr = ptr->next()) {
248        ASSERT(!ptr->elision());
249        tail = new (vm) ArgumentListNode(location, tail, ptr->value());
250    }
251    return head;
252}
253
254// ------------------------------ ObjectLiteralNode ----------------------------
255
256RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
257{
258     if (!m_list) {
259         if (dst == generator.ignoredResult())
260             return 0;
261         return generator.emitNewObject(generator.finalDestination(dst));
262     }
263     return generator.emitNode(dst, m_list);
264}
265
266// ------------------------------ PropertyListNode -----------------------------
267
268RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
269{
270    RefPtr<RegisterID> newObj = generator.tempDestination(dst);
271
272    generator.emitNewObject(newObj.get());
273
274    // Fast case: this loop just handles regular value properties.
275    PropertyListNode* p = this;
276    for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next) {
277        if (p->m_node->m_name) {
278            generator.emitDirectPutById(newObj.get(), *p->m_node->name(), generator.emitNode(p->m_node->m_assign));
279            continue;
280        }
281        RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression);
282        generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign));
283    }
284
285    // Were there any get/set properties?
286    if (p) {
287        typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
288        typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
289        GetterSetterMap map;
290
291        // Build a map, pairing get/set values together.
292        for (PropertyListNode* q = p; q; q = q->m_next) {
293            PropertyNode* node = q->m_node;
294            if (node->m_type == PropertyNode::Constant)
295                continue;
296
297            GetterSetterPair pair(node, static_cast<PropertyNode*>(0));
298            GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
299            if (!result.isNewEntry)
300                result.iterator->value.second = node;
301        }
302
303        // Iterate over the remaining properties in the list.
304        for (; p; p = p->m_next) {
305            PropertyNode* node = p->m_node;
306
307            // Handle regular values.
308            if (node->m_type == PropertyNode::Constant) {
309                if (node->name()) {
310                    generator.emitDirectPutById(newObj.get(), *node->name(), generator.emitNode(node->m_assign));
311                    continue;
312                }
313                RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression);
314                generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign));
315                continue;
316            }
317
318            RegisterID* value = generator.emitNode(node->m_assign);
319
320            // This is a get/set property, find its entry in the map.
321            ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
322            GetterSetterMap::iterator it = map.find(node->name()->impl());
323            ASSERT(it != map.end());
324            GetterSetterPair& pair = it->value;
325
326            // Was this already generated as a part of its partner?
327            if (pair.second == node)
328                continue;
329
330            // Generate the paired node now.
331            RefPtr<RegisterID> getterReg;
332            RefPtr<RegisterID> setterReg;
333
334            if (node->m_type == PropertyNode::Getter) {
335                getterReg = value;
336                if (pair.second) {
337                    ASSERT(pair.second->m_type == PropertyNode::Setter);
338                    setterReg = generator.emitNode(pair.second->m_assign);
339                } else {
340                    setterReg = generator.newTemporary();
341                    generator.emitLoad(setterReg.get(), jsUndefined());
342                }
343            } else {
344                ASSERT(node->m_type == PropertyNode::Setter);
345                setterReg = value;
346                if (pair.second) {
347                    ASSERT(pair.second->m_type == PropertyNode::Getter);
348                    getterReg = generator.emitNode(pair.second->m_assign);
349                } else {
350                    getterReg = generator.newTemporary();
351                    generator.emitLoad(getterReg.get(), jsUndefined());
352                }
353            }
354
355            generator.emitPutGetterSetter(newObj.get(), *node->name(), getterReg.get(), setterReg.get());
356        }
357    }
358
359    return generator.moveToDestinationIfNeeded(dst, newObj.get());
360}
361
362// ------------------------------ BracketAccessorNode --------------------------------
363
364RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
365{
366    if (m_base->isResolveNode()
367        && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())
368        && !generator.symbolTable().slowArguments()) {
369        RegisterID* property = generator.emitNode(m_subscript);
370        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
371        return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
372    }
373
374    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
375    RegisterID* property = generator.emitNode(m_subscript);
376    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
377    return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
378}
379
380// ------------------------------ DotAccessorNode --------------------------------
381
382RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
383{
384    if (m_ident == generator.propertyNames().length) {
385        if (!m_base->isResolveNode())
386            goto nonArgumentsPath;
387        ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
388        if (!generator.willResolveToArguments(resolveNode->identifier()))
389            goto nonArgumentsPath;
390        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
391        return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
392    }
393
394nonArgumentsPath:
395    RegisterID* base = generator.emitNode(m_base);
396    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
397    return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
398}
399
400// ------------------------------ ArgumentListNode -----------------------------
401
402RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
403{
404    ASSERT(m_expr);
405    return generator.emitNode(dst, m_expr);
406}
407
408// ------------------------------ NewExprNode ----------------------------------
409
410RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
411{
412    ExpectedFunction expectedFunction;
413    if (m_expr->isResolveNode())
414        expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
415    else
416        expectedFunction = NoExpectedFunction;
417    RefPtr<RegisterID> func = generator.emitNode(m_expr);
418    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
419    CallArguments callArguments(generator, m_args);
420    return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
421}
422
423CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
424    : m_argumentsNode(argumentsNode)
425    , m_padding(0)
426{
427    if (generator.shouldEmitProfileHooks())
428        m_profileHookRegister = generator.newTemporary();
429
430    size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
431    if (argumentsNode) {
432        for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
433            ++argumentCountIncludingThis;
434    }
435
436    m_argv.grow(argumentCountIncludingThis);
437    for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
438        m_argv[i] = generator.newTemporary();
439        ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() - 1);
440    }
441
442    while (stackOffset() % stackAlignmentRegisters()) {
443        m_argv.insert(0, generator.newTemporary());
444        m_padding++;
445    }
446}
447
448// ------------------------------ EvalFunctionCallNode ----------------------------------
449
450RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
451{
452    if (Local local = generator.local(generator.propertyNames().eval)) {
453        RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
454        CallArguments callArguments(generator, m_args);
455        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
456        return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
457    }
458
459    RefPtr<RegisterID> func = generator.newTemporary();
460    CallArguments callArguments(generator, m_args);
461    JSTextPosition newDivot = divotStart() + 4;
462    generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
463    generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval);
464    generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound);
465    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
466}
467
468// ------------------------------ FunctionCallValueNode ----------------------------------
469
470RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
471{
472    RefPtr<RegisterID> func = generator.emitNode(m_expr);
473    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
474    CallArguments callArguments(generator, m_args);
475    generator.emitLoad(callArguments.thisRegister(), jsUndefined());
476    return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
477}
478
479// ------------------------------ FunctionCallResolveNode ----------------------------------
480
481RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
482{
483    ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
484
485    if (Local local = generator.local(m_ident)) {
486        RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
487        RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
488        CallArguments callArguments(generator, m_args);
489        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
490        // This passes NoExpectedFunction because we expect that if the function is in a
491        // local variable, then it's not one of our built-in constructors.
492        return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
493    }
494
495    RefPtr<RegisterID> func = generator.newTemporary();
496    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
497    CallArguments callArguments(generator, m_args);
498
499    JSTextPosition newDivot = divotStart() + m_ident.length();
500    generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
501    generator.emitResolveScope(callArguments.thisRegister(), m_ident);
502    generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound);
503    return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
504}
505
506// ------------------------------ FunctionCallBracketNode ----------------------------------
507
508RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
509{
510    RefPtr<RegisterID> base = generator.emitNode(m_base);
511    RegisterID* property = generator.emitNode(m_subscript);
512    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
513    RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
514    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
515    CallArguments callArguments(generator, m_args);
516    generator.emitMove(callArguments.thisRegister(), base.get());
517    return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
518}
519
520// ------------------------------ FunctionCallDotNode ----------------------------------
521
522RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
523{
524    RefPtr<RegisterID> function = generator.tempDestination(dst);
525    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
526    CallArguments callArguments(generator, m_args);
527    generator.emitNode(callArguments.thisRegister(), m_base);
528    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
529    generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
530    return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
531}
532
533static RegisterID* getArgumentByVal(BytecodeGenerator& generator, ExpressionNode* base, RegisterID* property, RegisterID* dst, JSTextPosition divot, JSTextPosition divotStart, JSTextPosition divotEnd)
534{
535    if (base->isResolveNode()
536        && generator.willResolveToArguments(static_cast<ResolveNode*>(base)->identifier())
537        && !generator.symbolTable().slowArguments()) {
538        generator.emitExpressionInfo(divot, divotStart, divotEnd);
539        return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
540    }
541    return nullptr;
542}
543
544RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
545{
546    RefPtr<Label> realCall = generator.newLabel();
547    RefPtr<Label> end = generator.newLabel();
548    RefPtr<RegisterID> base = generator.emitNode(m_base);
549    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
550    RefPtr<RegisterID> function;
551    bool emitCallCheck = !generator.isBuiltinFunction();
552    if (emitCallCheck) {
553        function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
554        generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
555    }
556    RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
557    {
558        if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
559            RefPtr<RegisterID> profileHookRegister;
560            if (generator.shouldEmitProfileHooks())
561                profileHookRegister = generator.newTemporary();
562            SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
563            ExpressionNode* subject = spread->expression();
564            RefPtr<RegisterID> thisRegister = getArgumentByVal(generator, subject, generator.emitLoad(0, jsNumber(0)), 0, spread->divot(), spread->divotStart(), spread->divotEnd());
565            RefPtr<RegisterID> argumentsRegister;
566            if (thisRegister)
567                argumentsRegister = generator.uncheckedRegisterForArguments();
568            else {
569                argumentsRegister = generator.emitNode(subject);
570                generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
571                thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
572            }
573            generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
574        } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
575            ArgumentListNode* oldList = m_args->m_listNode;
576            m_args->m_listNode = m_args->m_listNode->m_next;
577
578            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
579            CallArguments callArguments(generator, m_args);
580            generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
581            generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
582            m_args->m_listNode = oldList;
583        } else {
584            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
585            CallArguments callArguments(generator, m_args);
586            generator.emitLoad(callArguments.thisRegister(), jsUndefined());
587            generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
588        }
589    }
590    if (emitCallCheck) {
591        generator.emitJump(end.get());
592        generator.emitLabel(realCall.get());
593        {
594            CallArguments callArguments(generator, m_args);
595            generator.emitMove(callArguments.thisRegister(), base.get());
596            generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
597        }
598        generator.emitLabel(end.get());
599    }
600    return returnValue.get();
601}
602
603static bool areTrivialApplyArguments(ArgumentsNode* args)
604{
605    return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
606        || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
607}
608
609RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
610{
611    // A few simple cases can be trivially handled as ordinary function calls.
612    // function.apply(), function.apply(arg) -> identical to function.call
613    // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
614    bool mayBeCall = areTrivialApplyArguments(m_args);
615
616    RefPtr<Label> realCall = generator.newLabel();
617    RefPtr<Label> end = generator.newLabel();
618    RefPtr<RegisterID> base = generator.emitNode(m_base);
619    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
620    RefPtr<RegisterID> function;
621    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
622    bool emitCallCheck = !generator.isBuiltinFunction();
623    if (emitCallCheck) {
624        function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
625        generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
626    }
627    if (mayBeCall) {
628        if (m_args->m_listNode && m_args->m_listNode->m_expr) {
629            ArgumentListNode* oldList = m_args->m_listNode;
630            if (m_args->m_listNode->m_expr->isSpreadExpression()) {
631                SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
632                RefPtr<RegisterID> profileHookRegister;
633                if (generator.shouldEmitProfileHooks())
634                    profileHookRegister = generator.newTemporary();
635                RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
636                RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
637                RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
638                RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
639
640                auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
641                {
642                    RefPtr<Label> haveThis = generator.newLabel();
643                    RefPtr<Label> end = generator.newLabel();
644                    RefPtr<RegisterID> compareResult = generator.newTemporary();
645                    RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
646                    generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
647                    generator.emitMove(thisRegister.get(), value);
648                    generator.emitLoad(index.get(), jsNumber(1));
649                    generator.emitJump(end.get());
650                    generator.emitLabel(haveThis.get());
651                    RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
652                    generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
653                    generator.emitMove(argumentsRegister.get(), value);
654                    generator.emitLoad(index.get(), jsNumber(2));
655                    generator.emitLabel(end.get());
656                };
657                generator.emitEnumeration(this, spread->expression(), extractor);
658                generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
659            } else if (m_args->m_listNode->m_next) {
660                ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
661                ASSERT(!m_args->m_listNode->m_next->m_next);
662                m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.vm(), 0, 0);
663                RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
664                CallArguments callArguments(generator, m_args);
665                generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
666                generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
667            } else {
668                m_args->m_listNode = m_args->m_listNode->m_next;
669                RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
670                CallArguments callArguments(generator, m_args);
671                generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
672                generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
673            }
674            m_args->m_listNode = oldList;
675        } else {
676            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
677            CallArguments callArguments(generator, m_args);
678            generator.emitLoad(callArguments.thisRegister(), jsUndefined());
679            generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
680        }
681    } else {
682        ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
683        RefPtr<RegisterID> profileHookRegister;
684        if (generator.shouldEmitProfileHooks())
685            profileHookRegister = generator.newTemporary();
686        RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
687        RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
688        RefPtr<RegisterID> argsRegister;
689        ArgumentListNode* args = m_args->m_listNode->m_next;
690        if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()) && !generator.symbolTable().slowArguments())
691            argsRegister = generator.uncheckedRegisterForArguments();
692        else
693            argsRegister = generator.emitNode(args->m_expr);
694
695        // Function.prototype.apply ignores extra arguments, but we still
696        // need to evaluate them for side effects.
697        while ((args = args->m_next))
698            generator.emitNode(args->m_expr);
699
700        generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
701    }
702    if (emitCallCheck) {
703        generator.emitJump(end.get());
704        generator.emitLabel(realCall.get());
705        CallArguments callArguments(generator, m_args);
706        generator.emitMove(callArguments.thisRegister(), base.get());
707        generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
708        generator.emitLabel(end.get());
709    }
710    return returnValue.get();
711}
712
713// ------------------------------ PostfixNode ----------------------------------
714
715static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
716{
717    return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
718}
719
720static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
721{
722    if (dst == srcDst)
723        return generator.emitToNumber(generator.finalDestination(dst), srcDst);
724    RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
725    emitIncOrDec(generator, srcDst, oper);
726    return generator.moveToDestinationIfNeeded(dst, tmp.get());
727}
728
729RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
730{
731    if (dst == generator.ignoredResult())
732        return PrefixNode::emitResolve(generator, dst);
733
734    ASSERT(m_expr->isResolveNode());
735    ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
736    const Identifier& ident = resolve->identifier();
737
738    if (Local local = generator.local(ident)) {
739        RegisterID* localReg = local.get();
740        if (local.isReadOnly()) {
741            generator.emitReadOnlyExceptionIfNeeded();
742            localReg = generator.emitMove(generator.tempDestination(dst), localReg);
743        } else if (local.isCaptured()) {
744            RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
745            ASSERT(dst != localReg);
746            RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
747            generator.emitToNumber(tempDst.get(), localReg);
748            generator.emitMove(tempDstSrc.get(), localReg);
749            emitIncOrDec(generator, tempDstSrc.get(), m_operator);
750            generator.emitMove(localReg, tempDstSrc.get());
751            return tempDst.get();
752        }
753        return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg, m_operator);
754    }
755
756    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
757    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident);
758    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
759    RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
760    generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
761    return oldValue.get();
762}
763
764RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
765{
766    if (dst == generator.ignoredResult())
767        return PrefixNode::emitBracket(generator, dst);
768
769    ASSERT(m_expr->isBracketAccessorNode());
770    BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
771    ExpressionNode* baseNode = bracketAccessor->base();
772    ExpressionNode* subscript = bracketAccessor->subscript();
773
774    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
775    RefPtr<RegisterID> property = generator.emitNode(subscript);
776
777    generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
778    RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
779    RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
780    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
781    generator.emitPutByVal(base.get(), property.get(), value.get());
782    return generator.moveToDestinationIfNeeded(dst, oldValue);
783}
784
785RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
786{
787    if (dst == generator.ignoredResult())
788        return PrefixNode::emitDot(generator, dst);
789
790    ASSERT(m_expr->isDotAccessorNode());
791    DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
792    ExpressionNode* baseNode = dotAccessor->base();
793    const Identifier& ident = dotAccessor->identifier();
794
795    RefPtr<RegisterID> base = generator.emitNode(baseNode);
796
797    generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
798    RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
799    RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
800    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
801    generator.emitPutById(base.get(), ident, value.get());
802    return generator.moveToDestinationIfNeeded(dst, oldValue);
803}
804
805RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
806{
807    if (m_expr->isResolveNode())
808        return emitResolve(generator, dst);
809
810    if (m_expr->isBracketAccessorNode())
811        return emitBracket(generator, dst);
812
813    if (m_expr->isDotAccessorNode())
814        return emitDot(generator, dst);
815
816    return emitThrowReferenceError(generator, m_operator == OpPlusPlus
817        ? "Postfix ++ operator applied to value that is not a reference."
818        : "Postfix -- operator applied to value that is not a reference.");
819}
820
821// ------------------------------ DeleteResolveNode -----------------------------------
822
823RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
824{
825    if (generator.local(m_ident).get())
826        return generator.emitLoad(generator.finalDestination(dst), false);
827
828    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
829    RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
830    return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
831}
832
833// ------------------------------ DeleteBracketNode -----------------------------------
834
835RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
836{
837    RefPtr<RegisterID> r0 = generator.emitNode(m_base);
838    RegisterID* r1 = generator.emitNode(m_subscript);
839
840    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
841    return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
842}
843
844// ------------------------------ DeleteDotNode -----------------------------------
845
846RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
847{
848    RegisterID* r0 = generator.emitNode(m_base);
849
850    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
851    return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
852}
853
854// ------------------------------ DeleteValueNode -----------------------------------
855
856RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
857{
858    generator.emitNode(generator.ignoredResult(), m_expr);
859
860    // delete on a non-location expression ignores the value and returns true
861    return generator.emitLoad(generator.finalDestination(dst), true);
862}
863
864// ------------------------------ VoidNode -------------------------------------
865
866RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
867{
868    if (dst == generator.ignoredResult()) {
869        generator.emitNode(generator.ignoredResult(), m_expr);
870        return 0;
871    }
872    RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
873    return generator.emitLoad(dst, jsUndefined());
874}
875
876// ------------------------------ TypeOfValueNode -----------------------------------
877
878RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
879{
880    if (Local local = generator.local(m_ident)) {
881        if (dst == generator.ignoredResult())
882            return 0;
883        return generator.emitTypeOf(generator.finalDestination(dst), local.get());
884    }
885
886    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
887    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
888    if (dst == generator.ignoredResult())
889        return 0;
890    return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
891}
892
893// ------------------------------ TypeOfValueNode -----------------------------------
894
895RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
896{
897    if (dst == generator.ignoredResult()) {
898        generator.emitNode(generator.ignoredResult(), m_expr);
899        return 0;
900    }
901    RefPtr<RegisterID> src = generator.emitNode(m_expr);
902    return generator.emitTypeOf(generator.finalDestination(dst), src.get());
903}
904
905// ------------------------------ PrefixNode ----------------------------------
906
907RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
908{
909    ASSERT(m_expr->isResolveNode());
910    ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
911    const Identifier& ident = resolve->identifier();
912
913    if (Local local = generator.local(ident)) {
914        RegisterID* localReg = local.get();
915        if (local.isReadOnly()) {
916            generator.emitReadOnlyExceptionIfNeeded();
917            localReg = generator.emitMove(generator.tempDestination(dst), localReg);
918        } else if (local.isCaptured()) {
919            RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
920            generator.emitMove(tempDst.get(), localReg);
921            emitIncOrDec(generator, tempDst.get(), m_operator);
922            generator.emitMove(localReg, tempDst.get());
923            return generator.moveToDestinationIfNeeded(dst, tempDst.get());
924        }
925        emitIncOrDec(generator, localReg, m_operator);
926        return generator.moveToDestinationIfNeeded(dst, localReg);
927    }
928
929    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
930    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident);
931    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
932    emitIncOrDec(generator, value.get(), m_operator);
933    generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
934    return generator.moveToDestinationIfNeeded(dst, value.get());
935}
936
937RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
938{
939    ASSERT(m_expr->isBracketAccessorNode());
940    BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
941    ExpressionNode* baseNode = bracketAccessor->base();
942    ExpressionNode* subscript = bracketAccessor->subscript();
943
944    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
945    RefPtr<RegisterID> property = generator.emitNode(subscript);
946    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
947
948    generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
949    RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
950    emitIncOrDec(generator, value, m_operator);
951    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
952    generator.emitPutByVal(base.get(), property.get(), value);
953    return generator.moveToDestinationIfNeeded(dst, propDst.get());
954}
955
956RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
957{
958    ASSERT(m_expr->isDotAccessorNode());
959    DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
960    ExpressionNode* baseNode = dotAccessor->base();
961    const Identifier& ident = dotAccessor->identifier();
962
963    RefPtr<RegisterID> base = generator.emitNode(baseNode);
964    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
965
966    generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
967    RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
968    emitIncOrDec(generator, value, m_operator);
969    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
970    generator.emitPutById(base.get(), ident, value);
971    return generator.moveToDestinationIfNeeded(dst, propDst.get());
972}
973
974RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
975{
976    if (m_expr->isResolveNode())
977        return emitResolve(generator, dst);
978
979    if (m_expr->isBracketAccessorNode())
980        return emitBracket(generator, dst);
981
982    if (m_expr->isDotAccessorNode())
983        return emitDot(generator, dst);
984
985    return emitThrowReferenceError(generator, m_operator == OpPlusPlus
986        ? "Prefix ++ operator applied to value that is not a reference."
987        : "Prefix -- operator applied to value that is not a reference.");
988}
989
990// ------------------------------ Unary Operation Nodes -----------------------------------
991
992RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
993{
994    RegisterID* src = generator.emitNode(m_expr);
995    generator.emitExpressionInfo(position(), position(), position());
996    return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
997}
998
999// ------------------------------ BitwiseNotNode -----------------------------------
1000
1001RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1002{
1003    RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
1004    RegisterID* src1 = generator.emitNode(m_expr);
1005    return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
1006}
1007
1008// ------------------------------ LogicalNotNode -----------------------------------
1009
1010void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1011{
1012    // reverse the true and false targets
1013    generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
1014}
1015
1016
1017// ------------------------------ Binary Operation Nodes -----------------------------------
1018
1019// BinaryOpNode::emitStrcat:
1020//
1021// This node generates an op_strcat operation.  This opcode can handle concatenation of three or
1022// more values, where we can determine a set of separate op_add operations would be operating on
1023// string values.
1024//
1025// This function expects to be operating on a graph of AST nodes looking something like this:
1026//
1027//     (a)...     (b)
1028//          \   /
1029//           (+)     (c)
1030//              \   /
1031//      [d]     ((+))
1032//         \    /
1033//          [+=]
1034//
1035// The assignment operation is optional, if it exists the register holding the value on the
1036// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1037//
1038// The method should be called on the node at the root of the tree of regular binary add
1039// operations (marked in the diagram with a double set of parentheses).  This node must
1040// be performing a string concatenation (determined by statically detecting that at least
1041// one child must be a string).
1042//
1043// Since the minimum number of values being concatenated together is expected to be 3, if
1044// a lhs to a concatenating assignment is not provided then the  root add should have at
1045// least one left child that is also an add that can be determined to be operating on strings.
1046//
1047RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1048{
1049    ASSERT(isAdd());
1050    ASSERT(resultDescriptor().definitelyIsString());
1051
1052    // Create a list of expressions for all the adds in the tree of nodes we can convert into
1053    // a string concatenation.  The rightmost node (c) is added first.  The rightmost node is
1054    // added first, and the leftmost child is never added, so the vector produced for the
1055    // example above will be [ c, b ].
1056    Vector<ExpressionNode*, 16> reverseExpressionList;
1057    reverseExpressionList.append(m_expr2);
1058
1059    // Examine the left child of the add.  So long as this is a string add, add its right-child
1060    // to the list, and keep processing along the left fork.
1061    ExpressionNode* leftMostAddChild = m_expr1;
1062    while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1063        reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1064        leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1065    }
1066
1067    Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1068
1069    // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1070    // We could possibly avoid this (the lhs is converted last anyway, we could let the
1071    // op_strcat node handle its conversion if required).
1072    if (lhs)
1073        temporaryRegisters.append(generator.newTemporary());
1074
1075    // Emit code for the leftmost node ((a) in the example).
1076    temporaryRegisters.append(generator.newTemporary());
1077    RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1078    generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1079
1080    // Note on ordering of conversions:
1081    //
1082    // We maintain the same ordering of conversions as we would see if the concatenations
1083    // was performed as a sequence of adds (otherwise this optimization could change
1084    // behaviour should an object have been provided a valueOf or toString method).
1085    //
1086    // Considering the above example, the sequnce of execution is:
1087    //     * evaluate operand (a)
1088    //     * evaluate operand (b)
1089    //     * convert (a) to primitive   <-  (this would be triggered by the first add)
1090    //     * convert (b) to primitive   <-  (ditto)
1091    //     * evaluate operand (c)
1092    //     * convert (c) to primitive   <-  (this would be triggered by the second add)
1093    // And optionally, if there is an assignment:
1094    //     * convert (d) to primitive   <-  (this would be triggered by the assigning addition)
1095    //
1096    // As such we do not plant an op to convert the leftmost child now.  Instead, use
1097    // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1098    // once the second node has been generated.  However, if the leftmost child is an
1099    // immediate we can trivially determine that no conversion will be required.
1100    // If this is the case
1101    if (leftMostAddChild->isString())
1102        leftMostAddChildTempRegister = 0;
1103
1104    while (reverseExpressionList.size()) {
1105        ExpressionNode* node = reverseExpressionList.last();
1106        reverseExpressionList.removeLast();
1107
1108        // Emit the code for the current node.
1109        temporaryRegisters.append(generator.newTemporary());
1110        generator.emitNode(temporaryRegisters.last().get(), node);
1111
1112        // On the first iteration of this loop, when we first reach this point we have just
1113        // generated the second node, which means it is time to convert the leftmost operand.
1114        if (leftMostAddChildTempRegister) {
1115            generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1116            leftMostAddChildTempRegister = 0; // Only do this once.
1117        }
1118        // Plant a conversion for this node, if necessary.
1119        if (!node->isString())
1120            generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1121    }
1122    ASSERT(temporaryRegisters.size() >= 3);
1123
1124    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1125    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1126    if (emitExpressionInfoForMe)
1127        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
1128    // If there is an assignment convert the lhs now.  This will also copy lhs to
1129    // the temporary register we allocated for it.
1130    if (lhs)
1131        generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1132
1133    return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1134}
1135
1136void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1137{
1138    TriState branchCondition;
1139    ExpressionNode* branchExpression;
1140    tryFoldToBranch(generator, branchCondition, branchExpression);
1141
1142    if (branchCondition == MixedTriState)
1143        ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1144    else if (branchCondition == TrueTriState)
1145        generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1146    else
1147        generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1148}
1149
1150static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1151{
1152    ResultType expressionType = branchExpression->resultDescriptor();
1153
1154    if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1155        return true;
1156    else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1157        return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1158    else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1159        return true;
1160
1161    return false;
1162}
1163
1164void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1165{
1166    branchCondition = MixedTriState;
1167    branchExpression = 0;
1168
1169    ConstantNode* constant = 0;
1170    if (m_expr1->isConstant()) {
1171        constant = static_cast<ConstantNode*>(m_expr1);
1172        branchExpression = m_expr2;
1173    } else if (m_expr2->isConstant()) {
1174        constant = static_cast<ConstantNode*>(m_expr2);
1175        branchExpression = m_expr1;
1176    }
1177
1178    if (!constant)
1179        return;
1180    ASSERT(branchExpression);
1181
1182    OpcodeID opcodeID = this->opcodeID();
1183    JSValue value = constant->jsValue(generator);
1184    bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1185    if (!canFoldToBranch)
1186        return;
1187
1188    if (opcodeID == op_eq || opcodeID == op_stricteq)
1189        branchCondition = triState(value.pureToBoolean());
1190    else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1191        branchCondition = triState(!value.pureToBoolean());
1192}
1193
1194RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1195{
1196    OpcodeID opcodeID = this->opcodeID();
1197
1198    if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
1199        generator.emitExpressionInfo(position(), position(), position());
1200        return emitStrcat(generator, dst);
1201    }
1202
1203    if (opcodeID == op_neq) {
1204        if (m_expr1->isNull() || m_expr2->isNull()) {
1205            RefPtr<RegisterID> src = generator.tempDestination(dst);
1206            generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1207            return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1208        }
1209    }
1210
1211    ExpressionNode* left = m_expr1;
1212    ExpressionNode* right = m_expr2;
1213    if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1214        if (left->isString())
1215            std::swap(left, right);
1216    }
1217
1218    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
1219    bool wasTypeof = generator.m_lastOpcodeID == op_typeof;
1220    RegisterID* src2 = generator.emitNode(right);
1221    generator.emitExpressionInfo(position(), position(), position());
1222    if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
1223        RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1224        if (opcodeID == op_neq)
1225            generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1226        else if (opcodeID == op_nstricteq)
1227            generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1228        else
1229            RELEASE_ASSERT_NOT_REACHED();
1230        return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1231    }
1232    RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
1233    if (opcodeID == op_urshift && dst != generator.ignoredResult())
1234        return generator.emitUnaryOp(op_unsigned, result, result);
1235    return result;
1236}
1237
1238RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1239{
1240    if (m_expr1->isNull() || m_expr2->isNull()) {
1241        RefPtr<RegisterID> src = generator.tempDestination(dst);
1242        generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1243        return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1244    }
1245
1246    ExpressionNode* left = m_expr1;
1247    ExpressionNode* right = m_expr2;
1248    if (left->isString())
1249        std::swap(left, right);
1250
1251    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
1252    RegisterID* src2 = generator.emitNode(right);
1253    return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1254}
1255
1256RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1257{
1258    ExpressionNode* left = m_expr1;
1259    ExpressionNode* right = m_expr2;
1260    if (left->isString())
1261        std::swap(left, right);
1262
1263    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
1264    RegisterID* src2 = generator.emitNode(right);
1265    return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1266}
1267
1268RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1269{
1270    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1271    RegisterID* src2 = generator.emitNode(m_expr2);
1272    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1273    return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1274}
1275
1276RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1277{
1278    RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1279    RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
1280    RefPtr<RegisterID> prototype = generator.newTemporary();
1281    RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1282    RefPtr<Label> target = generator.newLabel();
1283
1284    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1285    generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
1286
1287    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1288    generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
1289
1290    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1291    RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
1292    generator.emitLabel(target.get());
1293    return result;
1294}
1295
1296// ------------------------------ LogicalOpNode ----------------------------
1297
1298RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1299{
1300    RefPtr<RegisterID> temp = generator.tempDestination(dst);
1301    RefPtr<Label> target = generator.newLabel();
1302
1303    generator.emitNode(temp.get(), m_expr1);
1304    if (m_operator == OpLogicalAnd)
1305        generator.emitJumpIfFalse(temp.get(), target.get());
1306    else
1307        generator.emitJumpIfTrue(temp.get(), target.get());
1308    generator.emitNode(temp.get(), m_expr2);
1309    generator.emitLabel(target.get());
1310
1311    return generator.moveToDestinationIfNeeded(dst, temp.get());
1312}
1313
1314void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1315{
1316    RefPtr<Label> afterExpr1 = generator.newLabel();
1317    if (m_operator == OpLogicalAnd)
1318        generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1319    else
1320        generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1321    generator.emitLabel(afterExpr1.get());
1322
1323    generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
1324}
1325
1326// ------------------------------ ConditionalNode ------------------------------
1327
1328RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1329{
1330    RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1331    RefPtr<Label> beforeElse = generator.newLabel();
1332    RefPtr<Label> afterElse = generator.newLabel();
1333
1334    RefPtr<Label> beforeThen = generator.newLabel();
1335    generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1336    generator.emitLabel(beforeThen.get());
1337
1338    generator.emitNode(newDst.get(), m_expr1);
1339    generator.emitJump(afterElse.get());
1340
1341    generator.emitLabel(beforeElse.get());
1342    generator.emitNode(newDst.get(), m_expr2);
1343
1344    generator.emitLabel(afterElse.get());
1345
1346    return newDst.get();
1347}
1348
1349// ------------------------------ ReadModifyResolveNode -----------------------------------
1350
1351// FIXME: should this be moved to be a method on BytecodeGenerator?
1352static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1353{
1354    OpcodeID opcodeID;
1355    switch (oper) {
1356        case OpMultEq:
1357            opcodeID = op_mul;
1358            break;
1359        case OpDivEq:
1360            opcodeID = op_div;
1361            break;
1362        case OpPlusEq:
1363            if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1364                return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1365            opcodeID = op_add;
1366            break;
1367        case OpMinusEq:
1368            opcodeID = op_sub;
1369            break;
1370        case OpLShift:
1371            opcodeID = op_lshift;
1372            break;
1373        case OpRShift:
1374            opcodeID = op_rshift;
1375            break;
1376        case OpURShift:
1377            opcodeID = op_urshift;
1378            break;
1379        case OpAndEq:
1380            opcodeID = op_bitand;
1381            break;
1382        case OpXOrEq:
1383            opcodeID = op_bitxor;
1384            break;
1385        case OpOrEq:
1386            opcodeID = op_bitor;
1387            break;
1388        case OpModEq:
1389            opcodeID = op_mod;
1390            break;
1391        default:
1392            RELEASE_ASSERT_NOT_REACHED();
1393            return dst;
1394    }
1395
1396    RegisterID* src2 = generator.emitNode(m_right);
1397
1398    // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1399    // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1400    if (emitExpressionInfoForMe)
1401        generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
1402    RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1403    if (oper == OpURShift)
1404        return generator.emitUnaryOp(op_unsigned, result, result);
1405    return result;
1406}
1407
1408RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1409{
1410    if (Local local = generator.local(m_ident)) {
1411        if (local.isReadOnly()) {
1412            generator.emitReadOnlyExceptionIfNeeded();
1413            return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1414        }
1415
1416        if (local.isCaptured()
1417            || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1418            RefPtr<RegisterID> result = generator.newTemporary();
1419            generator.emitMove(result.get(), local.get());
1420            emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1421            generator.emitMove(local.get(), result.get());
1422            return generator.moveToDestinationIfNeeded(dst, result.get());
1423        }
1424
1425        RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1426        return generator.moveToDestinationIfNeeded(dst, result);
1427    }
1428
1429    JSTextPosition newDivot = divotStart() + m_ident.length();
1430    generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
1431    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1432    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound);
1433    RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
1434    return generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound);
1435}
1436
1437// ------------------------------ AssignResolveNode -----------------------------------
1438
1439RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1440{
1441    if (Local local = generator.local(m_ident)) {
1442        if (local.isReadOnly()) {
1443            generator.emitReadOnlyExceptionIfNeeded();
1444            return generator.emitNode(dst, m_right);
1445        }
1446        if (local.isCaptured()) {
1447            RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1448            generator.emitNode(tempDst.get(), m_right);
1449            generator.emitMove(local.get(), tempDst.get());
1450            return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1451        }
1452        RegisterID* result = generator.emitNode(local.get(), m_right);
1453        return generator.moveToDestinationIfNeeded(dst, result);
1454    }
1455
1456    if (generator.isStrictMode())
1457        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1458    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1459    if (dst == generator.ignoredResult())
1460        dst = 0;
1461    RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
1462    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1463    return generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
1464}
1465
1466// ------------------------------ AssignDotNode -----------------------------------
1467
1468RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1469{
1470    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1471    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1472    RegisterID* result = generator.emitNode(value.get(), m_right);
1473    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1474    RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1475    generator.emitPutById(base.get(), m_ident, forwardResult);
1476    return generator.moveToDestinationIfNeeded(dst, forwardResult);
1477}
1478
1479// ------------------------------ ReadModifyDotNode -----------------------------------
1480
1481RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1482{
1483    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1484
1485    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1486    RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1487    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, static_cast<JSC::Operator>(m_operator), OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1488
1489    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1490    return generator.emitPutById(base.get(), m_ident, updatedValue);
1491}
1492
1493// ------------------------------ AssignErrorNode -----------------------------------
1494
1495RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1496{
1497    return emitThrowReferenceError(generator, "Left side of assignment is not a reference.");
1498}
1499
1500// ------------------------------ AssignBracketNode -----------------------------------
1501
1502RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1503{
1504    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1505    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1506    RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1507    RegisterID* result = generator.emitNode(value.get(), m_right);
1508
1509    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1510    RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1511    generator.emitPutByVal(base.get(), property.get(), forwardResult);
1512    return generator.moveToDestinationIfNeeded(dst, forwardResult);
1513}
1514
1515// ------------------------------ ReadModifyBracketNode -----------------------------------
1516
1517RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1518{
1519    RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1520    RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1521
1522    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1523    RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1524    RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, static_cast<JSC::Operator>(m_operator), OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1525
1526    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1527    generator.emitPutByVal(base.get(), property.get(), updatedValue);
1528
1529    return updatedValue;
1530}
1531
1532// ------------------------------ CommaNode ------------------------------------
1533
1534RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1535{
1536    ASSERT(m_expressions.size() > 1);
1537    for (size_t i = 0; i < m_expressions.size() - 1; i++)
1538        generator.emitNode(generator.ignoredResult(), m_expressions[i]);
1539    return generator.emitNode(dst, m_expressions.last());
1540}
1541
1542// ------------------------------ ConstDeclNode ------------------------------------
1543
1544RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1545{
1546    // FIXME: This code does not match the behavior of const in Firefox.
1547    if (Local local = generator.constLocal(m_ident)) {
1548        if (!m_init)
1549            return local.get();
1550
1551        if (local.isCaptured()) {
1552            RefPtr<RegisterID> tempDst = generator.newTemporary();
1553            generator.emitNode(tempDst.get(), m_init);
1554            return generator.emitMove(local.get(), tempDst.get());
1555        }
1556
1557        return generator.emitNode(local.get(), m_init);
1558    }
1559
1560    RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1561
1562    if (generator.codeType() == GlobalCode)
1563        return generator.emitInitGlobalConst(m_ident, value.get());
1564
1565    if (generator.codeType() != EvalCode)
1566        return value.get();
1567
1568    // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
1569    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1570    return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound);
1571}
1572
1573RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1574{
1575    RegisterID* result = 0;
1576    for (ConstDeclNode* n = this; n; n = n->m_next)
1577        result = n->emitCodeSingle(generator);
1578
1579    return result;
1580}
1581
1582// ------------------------------ ConstStatementNode -----------------------------
1583
1584void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1585{
1586    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1587    generator.emitNode(m_next);
1588}
1589
1590// ------------------------------ SourceElements -------------------------------
1591
1592
1593inline StatementNode* SourceElements::lastStatement() const
1594{
1595    size_t size = m_statements.size();
1596    return size ? m_statements[size - 1] : 0;
1597}
1598
1599inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1600{
1601    size_t size = m_statements.size();
1602    for (size_t i = 0; i < size; ++i)
1603        generator.emitNode(dst, m_statements[i]);
1604}
1605
1606// ------------------------------ BlockNode ------------------------------------
1607
1608inline StatementNode* BlockNode::lastStatement() const
1609{
1610    return m_statements ? m_statements->lastStatement() : 0;
1611}
1612
1613inline StatementNode* BlockNode::singleStatement() const
1614{
1615    return m_statements ? m_statements->singleStatement() : 0;
1616}
1617
1618void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1619{
1620    if (!m_statements)
1621        return;
1622    m_statements->emitBytecode(generator, dst);
1623}
1624
1625// ------------------------------ EmptyStatementNode ---------------------------
1626
1627void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1628{
1629    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1630}
1631
1632// ------------------------------ DebuggerStatementNode ---------------------------
1633
1634void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1635{
1636    generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
1637}
1638
1639// ------------------------------ ExprStatementNode ----------------------------
1640
1641void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1642{
1643    ASSERT(m_expr);
1644    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1645    generator.emitNode(dst, m_expr);
1646}
1647
1648// ------------------------------ VarStatementNode ----------------------------
1649
1650void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1651{
1652    ASSERT(m_expr);
1653    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1654    generator.emitNode(m_expr);
1655}
1656
1657// ------------------------------ IfElseNode ---------------------------------------
1658
1659static inline StatementNode* singleStatement(StatementNode* statementNode)
1660{
1661    if (statementNode->isBlock())
1662        return static_cast<BlockNode*>(statementNode)->singleStatement();
1663    return statementNode;
1664}
1665
1666bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
1667    Label*& trueTarget, FallThroughMode& fallThroughMode)
1668{
1669    StatementNode* singleStatement = JSC::singleStatement(ifBlock);
1670    if (!singleStatement)
1671        return false;
1672
1673    if (singleStatement->isBreak()) {
1674        BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
1675        Label* target = breakNode->trivialTarget(generator);
1676        if (!target)
1677            return false;
1678        trueTarget = target;
1679        fallThroughMode = FallThroughMeansFalse;
1680        return true;
1681    }
1682
1683    if (singleStatement->isContinue()) {
1684        ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
1685        Label* target = continueNode->trivialTarget(generator);
1686        if (!target)
1687            return false;
1688        trueTarget = target;
1689        fallThroughMode = FallThroughMeansFalse;
1690        return true;
1691    }
1692
1693    return false;
1694}
1695
1696void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1697{
1698    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1699
1700    RefPtr<Label> beforeThen = generator.newLabel();
1701    RefPtr<Label> beforeElse = generator.newLabel();
1702    RefPtr<Label> afterElse = generator.newLabel();
1703
1704    Label* trueTarget = beforeThen.get();
1705    Label* falseTarget = beforeElse.get();
1706    FallThroughMode fallThroughMode = FallThroughMeansTrue;
1707    bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
1708
1709    generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
1710    generator.emitLabel(beforeThen.get());
1711
1712    if (!didFoldIfBlock) {
1713        generator.emitNode(dst, m_ifBlock);
1714        if (m_elseBlock)
1715            generator.emitJump(afterElse.get());
1716    }
1717
1718    generator.emitLabel(beforeElse.get());
1719
1720    if (m_elseBlock)
1721        generator.emitNode(dst, m_elseBlock);
1722
1723    generator.emitLabel(afterElse.get());
1724}
1725
1726// ------------------------------ DoWhileNode ----------------------------------
1727
1728void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1729{
1730    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1731
1732    RefPtr<Label> topOfLoop = generator.newLabel();
1733    generator.emitLabel(topOfLoop.get());
1734    generator.emitLoopHint();
1735    generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
1736
1737    generator.emitNode(dst, m_statement);
1738
1739    generator.emitLabel(scope->continueTarget());
1740    generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
1741    generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1742
1743    generator.emitLabel(scope->breakTarget());
1744}
1745
1746// ------------------------------ WhileNode ------------------------------------
1747
1748void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1749{
1750    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1751    RefPtr<Label> topOfLoop = generator.newLabel();
1752
1753    generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->startOffset(), m_expr->lineStartOffset());
1754    generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
1755
1756    generator.emitLabel(topOfLoop.get());
1757    generator.emitLoopHint();
1758
1759    generator.emitNode(dst, m_statement);
1760
1761    generator.emitLabel(scope->continueTarget());
1762    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1763
1764    generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1765
1766    generator.emitLabel(scope->breakTarget());
1767}
1768
1769// ------------------------------ ForNode --------------------------------------
1770
1771void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1772{
1773    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1774
1775    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1776
1777    if (m_expr1)
1778        generator.emitNode(generator.ignoredResult(), m_expr1);
1779
1780    RefPtr<Label> topOfLoop = generator.newLabel();
1781    if (m_expr2)
1782        generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
1783
1784    generator.emitLabel(topOfLoop.get());
1785    generator.emitLoopHint();
1786
1787    generator.emitNode(dst, m_statement);
1788
1789    generator.emitLabel(scope->continueTarget());
1790    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1791    if (m_expr3)
1792        generator.emitNode(generator.ignoredResult(), m_expr3);
1793
1794    if (m_expr2)
1795        generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1796    else
1797        generator.emitJump(topOfLoop.get());
1798
1799    generator.emitLabel(scope->breakTarget());
1800}
1801
1802// ------------------------------ ForInNode ------------------------------------
1803
1804void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1805{
1806    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1807
1808    if (!m_lexpr->isAssignmentLocation()) {
1809        emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
1810        return;
1811    }
1812
1813    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1814
1815    RefPtr<RegisterID> base = generator.newTemporary();
1816    generator.emitNode(base.get(), m_expr);
1817    RefPtr<RegisterID> i = generator.newTemporary();
1818    RefPtr<RegisterID> size = generator.newTemporary();
1819    RefPtr<RegisterID> expectedSubscript;
1820    RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
1821    generator.emitJump(scope->continueTarget());
1822
1823    RefPtr<Label> loopStart = generator.newLabel();
1824    generator.emitLabel(loopStart.get());
1825    generator.emitLoopHint();
1826
1827    RegisterID* propertyName;
1828    bool optimizedForinAccess = false;
1829    if (m_lexpr->isResolveNode()) {
1830        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1831        Local local = generator.local(ident);
1832        if (!local.get()) {
1833            propertyName = generator.newTemporary();
1834            RefPtr<RegisterID> protect = propertyName;
1835            if (generator.isStrictMode())
1836                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1837            RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
1838            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1839            generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
1840        } else {
1841            expectedSubscript = generator.newTemporary();
1842            propertyName = expectedSubscript.get();
1843            generator.emitMove(local.get(), propertyName);
1844            generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), local.get());
1845            optimizedForinAccess = true;
1846        }
1847    } else if (m_lexpr->isDotAccessorNode()) {
1848        DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1849        const Identifier& ident = assignNode->identifier();
1850        propertyName = generator.newTemporary();
1851        RefPtr<RegisterID> protect = propertyName;
1852        RegisterID* base = generator.emitNode(assignNode->base());
1853
1854        generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1855        generator.emitPutById(base, ident, propertyName);
1856    } else if (m_lexpr->isBracketAccessorNode()) {
1857        BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1858        propertyName = generator.newTemporary();
1859        RefPtr<RegisterID> protect = propertyName;
1860        RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1861        RegisterID* subscript = generator.emitNode(assignNode->subscript());
1862
1863        generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1864        generator.emitPutByVal(base.get(), subscript, propertyName);
1865    } else {
1866        ASSERT(m_lexpr->isDeconstructionNode());
1867        DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
1868        auto binding = assignNode->bindings();
1869        if (binding->isBindingNode()) {
1870            auto simpleBinding = static_cast<BindingNode*>(binding);
1871            Identifier ident = simpleBinding->boundProperty();
1872            Local local = generator.local(ident);
1873            propertyName = local.get();
1874            if (!propertyName || local.isCaptured())
1875                goto genericBinding;
1876            expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
1877            generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
1878            optimizedForinAccess = true;
1879            goto completedSimpleBinding;
1880        } else {
1881        genericBinding:
1882            propertyName = generator.newTemporary();
1883            RefPtr<RegisterID> protect(propertyName);
1884            assignNode->bindings()->bindValue(generator, propertyName);
1885        }
1886        completedSimpleBinding:
1887        ;
1888    }
1889
1890    generator.emitNode(dst, m_statement);
1891
1892    if (optimizedForinAccess)
1893        generator.popOptimisedForIn();
1894
1895    generator.emitLabel(scope->continueTarget());
1896    generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
1897    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1898    generator.emitLabel(scope->breakTarget());
1899}
1900
1901// ------------------------------ ForOfNode ------------------------------------
1902void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1903{
1904    if (!m_lexpr->isAssignmentLocation()) {
1905        emitThrowReferenceError(generator, "Left side of for-of statement is not a reference.");
1906        return;
1907    }
1908
1909    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1910
1911    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1912    auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
1913    {
1914        if (m_lexpr->isResolveNode()) {
1915            const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1916            if (Local local = generator.local(ident))
1917                generator.emitMove(local.get(), value);
1918            else {
1919                if (generator.isStrictMode())
1920                    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1921                RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
1922                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1923                generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
1924            }
1925        } else if (m_lexpr->isDotAccessorNode()) {
1926            DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1927            const Identifier& ident = assignNode->identifier();
1928            RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1929
1930            generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1931            generator.emitPutById(base.get(), ident, value);
1932        } else if (m_lexpr->isBracketAccessorNode()) {
1933            BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1934            RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1935            RegisterID* subscript = generator.emitNode(assignNode->subscript());
1936
1937            generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1938            generator.emitPutByVal(base.get(), subscript, value);
1939        } else {
1940            ASSERT(m_lexpr->isDeconstructionNode());
1941            DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
1942            assignNode->bindings()->bindValue(generator, value);
1943        }
1944        generator.emitNode(dst, m_statement);
1945    };
1946    generator.emitEnumeration(this, m_expr, extractor);
1947}
1948
1949// ------------------------------ ContinueNode ---------------------------------
1950
1951Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
1952{
1953    if (generator.shouldEmitDebugHooks())
1954        return 0;
1955
1956    LabelScopePtr scope = generator.continueTarget(m_ident);
1957    ASSERT(scope);
1958
1959    if (generator.scopeDepth() != scope->scopeDepth())
1960        return 0;
1961
1962    return scope->continueTarget();
1963}
1964
1965void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1966{
1967    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1968
1969    LabelScopePtr scope = generator.continueTarget(m_ident);
1970    ASSERT(scope);
1971
1972    generator.emitPopScopes(scope->scopeDepth());
1973    generator.emitJump(scope->continueTarget());
1974}
1975
1976// ------------------------------ BreakNode ------------------------------------
1977
1978Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
1979{
1980    if (generator.shouldEmitDebugHooks())
1981        return 0;
1982
1983    LabelScopePtr scope = generator.breakTarget(m_ident);
1984    ASSERT(scope);
1985
1986    if (generator.scopeDepth() != scope->scopeDepth())
1987        return 0;
1988
1989    return scope->breakTarget();
1990}
1991
1992void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1993{
1994    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1995
1996    LabelScopePtr scope = generator.breakTarget(m_ident);
1997    ASSERT(scope);
1998
1999    generator.emitPopScopes(scope->scopeDepth());
2000    generator.emitJump(scope->breakTarget());
2001}
2002
2003// ------------------------------ ReturnNode -----------------------------------
2004
2005void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2006{
2007    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2008    ASSERT(generator.codeType() == FunctionCode);
2009
2010    if (dst == generator.ignoredResult())
2011        dst = 0;
2012
2013    RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
2014    if (generator.scopeDepth()) {
2015        returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
2016        generator.emitPopScopes(0);
2017    }
2018
2019    generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
2020    generator.emitReturn(returnRegister.get());
2021}
2022
2023// ------------------------------ WithNode -------------------------------------
2024
2025void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2026{
2027    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2028
2029    RefPtr<RegisterID> scope = generator.emitNode(m_expr);
2030    generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
2031    generator.emitPushWithScope(scope.get());
2032    generator.emitNode(dst, m_statement);
2033    generator.emitPopScope();
2034}
2035
2036// ------------------------------ CaseClauseNode --------------------------------
2037
2038inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2039{
2040    if (!m_statements)
2041        return;
2042    m_statements->emitBytecode(generator, dst);
2043}
2044
2045// ------------------------------ CaseBlockNode --------------------------------
2046
2047enum SwitchKind {
2048    SwitchUnset = 0,
2049    SwitchNumber = 1,
2050    SwitchString = 2,
2051    SwitchNeither = 3
2052};
2053
2054static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2055{
2056    for (; list; list = list->getNext()) {
2057        ExpressionNode* clauseExpression = list->getClause()->expr();
2058        literalVector.append(clauseExpression);
2059        if (clauseExpression->isNumber()) {
2060            double value = static_cast<NumberNode*>(clauseExpression)->value();
2061            int32_t intVal = static_cast<int32_t>(value);
2062            if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
2063                typeForTable = SwitchNeither;
2064                break;
2065            }
2066            if (intVal < min_num)
2067                min_num = intVal;
2068            if (intVal > max_num)
2069                max_num = intVal;
2070            typeForTable = SwitchNumber;
2071            continue;
2072        }
2073        if (clauseExpression->isString()) {
2074            if (typeForTable & ~SwitchString) {
2075                typeForTable = SwitchNeither;
2076                break;
2077            }
2078            const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
2079            if (singleCharacterSwitch &= value.length() == 1) {
2080                int32_t intVal = value[0];
2081                if (intVal < min_num)
2082                    min_num = intVal;
2083                if (intVal > max_num)
2084                    max_num = intVal;
2085            }
2086            typeForTable = SwitchString;
2087            continue;
2088        }
2089        typeForTable = SwitchNeither;
2090        break;
2091    }
2092}
2093
2094static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
2095{
2096    size_t length = 0;
2097    for (ClauseListNode* node = list1; node; node = node->getNext())
2098        ++length;
2099    for (ClauseListNode* node = list2; node; node = node->getNext())
2100        ++length;
2101    return length;
2102}
2103
2104SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2105{
2106    if (length(m_list1, m_list2) < s_tableSwitchMinimum)
2107        return SwitchInfo::SwitchNone;
2108
2109    SwitchKind typeForTable = SwitchUnset;
2110    bool singleCharacterSwitch = true;
2111
2112    processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2113    processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2114
2115    if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2116        return SwitchInfo::SwitchNone;
2117
2118    if (typeForTable == SwitchNumber) {
2119        int32_t range = max_num - min_num;
2120        if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2121            return SwitchInfo::SwitchImmediate;
2122        return SwitchInfo::SwitchNone;
2123    }
2124
2125    ASSERT(typeForTable == SwitchString);
2126
2127    if (singleCharacterSwitch) {
2128        int32_t range = max_num - min_num;
2129        if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2130            return SwitchInfo::SwitchCharacter;
2131    }
2132
2133    return SwitchInfo::SwitchString;
2134}
2135
2136void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
2137{
2138    RefPtr<Label> defaultLabel;
2139    Vector<RefPtr<Label>, 8> labelVector;
2140    Vector<ExpressionNode*, 8> literalVector;
2141    int32_t min_num = std::numeric_limits<int32_t>::max();
2142    int32_t max_num = std::numeric_limits<int32_t>::min();
2143    SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
2144
2145    if (switchType != SwitchInfo::SwitchNone) {
2146        // Prepare the various labels
2147        for (uint32_t i = 0; i < literalVector.size(); i++)
2148            labelVector.append(generator.newLabel());
2149        defaultLabel = generator.newLabel();
2150        generator.beginSwitch(switchExpression, switchType);
2151    } else {
2152        // Setup jumps
2153        for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2154            RefPtr<RegisterID> clauseVal = generator.newTemporary();
2155            generator.emitNode(clauseVal.get(), list->getClause()->expr());
2156            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2157            labelVector.append(generator.newLabel());
2158            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2159        }
2160
2161        for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2162            RefPtr<RegisterID> clauseVal = generator.newTemporary();
2163            generator.emitNode(clauseVal.get(), list->getClause()->expr());
2164            generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2165            labelVector.append(generator.newLabel());
2166            generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2167        }
2168        defaultLabel = generator.newLabel();
2169        generator.emitJump(defaultLabel.get());
2170    }
2171
2172    size_t i = 0;
2173    for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2174        generator.emitLabel(labelVector[i++].get());
2175        list->getClause()->emitBytecode(generator, dst);
2176    }
2177
2178    if (m_defaultClause) {
2179        generator.emitLabel(defaultLabel.get());
2180        m_defaultClause->emitBytecode(generator, dst);
2181    }
2182
2183    for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2184        generator.emitLabel(labelVector[i++].get());
2185        list->getClause()->emitBytecode(generator, dst);
2186    }
2187    if (!m_defaultClause)
2188        generator.emitLabel(defaultLabel.get());
2189
2190    ASSERT(i == labelVector.size());
2191    if (switchType != SwitchInfo::SwitchNone) {
2192        ASSERT(labelVector.size() == literalVector.size());
2193        generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2194    }
2195}
2196
2197// ------------------------------ SwitchNode -----------------------------------
2198
2199void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2200{
2201    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2202
2203    LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
2204
2205    RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
2206    m_block->emitBytecodeForBlock(generator, r0.get(), dst);
2207
2208    generator.emitLabel(scope->breakTarget());
2209}
2210
2211// ------------------------------ LabelNode ------------------------------------
2212
2213void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2214{
2215    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2216
2217    ASSERT(!generator.breakTarget(m_name));
2218
2219    LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
2220    generator.emitNode(dst, m_statement);
2221
2222    generator.emitLabel(scope->breakTarget());
2223}
2224
2225// ------------------------------ ThrowNode ------------------------------------
2226
2227void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2228{
2229    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2230
2231    if (dst == generator.ignoredResult())
2232        dst = 0;
2233    RefPtr<RegisterID> expr = generator.emitNode(m_expr);
2234    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2235    generator.emitThrow(expr.get());
2236}
2237
2238// ------------------------------ TryNode --------------------------------------
2239
2240void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2241{
2242    // NOTE: The catch and finally blocks must be labeled explicitly, so the
2243    // optimizer knows they may be jumped to from anywhere.
2244
2245    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2246
2247    ASSERT(m_catchBlock || m_finallyBlock);
2248
2249    RefPtr<Label> tryStartLabel = generator.newLabel();
2250    generator.emitLabel(tryStartLabel.get());
2251
2252    if (m_finallyBlock)
2253        generator.pushFinallyContext(m_finallyBlock);
2254    TryData* tryData = generator.pushTry(tryStartLabel.get());
2255
2256    generator.emitNode(dst, m_tryBlock);
2257
2258    if (m_catchBlock) {
2259        RefPtr<Label> catchEndLabel = generator.newLabel();
2260
2261        // Normal path: jump over the catch block.
2262        generator.emitJump(catchEndLabel.get());
2263
2264        // Uncaught exception path: the catch block.
2265        RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
2266        RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
2267
2268        if (m_finallyBlock) {
2269            // If the catch block throws an exception and we have a finally block, then the finally
2270            // block should "catch" that exception.
2271            tryData = generator.pushTry(here.get());
2272        }
2273
2274        generator.emitPushCatchScope(m_exceptionIdent, exceptionRegister.get(), DontDelete);
2275        generator.emitNode(dst, m_catchBlock);
2276        generator.emitPopScope();
2277        generator.emitLabel(catchEndLabel.get());
2278    }
2279
2280    if (m_finallyBlock) {
2281        RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2282
2283        generator.popFinallyContext();
2284
2285        RefPtr<Label> finallyEndLabel = generator.newLabel();
2286
2287        // Normal path: run the finally code, and jump to the end.
2288        generator.emitNode(dst, m_finallyBlock);
2289        generator.emitJump(finallyEndLabel.get());
2290
2291        // Uncaught exception path: invoke the finally block, then re-throw the exception.
2292        RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
2293        generator.emitNode(dst, m_finallyBlock);
2294        generator.emitThrow(tempExceptionRegister.get());
2295
2296        generator.emitLabel(finallyEndLabel.get());
2297    }
2298}
2299
2300// ------------------------------ ScopeNode -----------------------------
2301
2302inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2303{
2304    if (!m_statements)
2305        return;
2306    m_statements->emitBytecode(generator, dst);
2307}
2308
2309// ------------------------------ ProgramNode -----------------------------
2310
2311void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2312{
2313    generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
2314
2315    RefPtr<RegisterID> dstRegister = generator.newTemporary();
2316    generator.emitLoad(dstRegister.get(), jsUndefined());
2317    emitStatementsBytecode(generator, dstRegister.get());
2318
2319    generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
2320    generator.emitEnd(dstRegister.get());
2321}
2322
2323// ------------------------------ EvalNode -----------------------------
2324
2325void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2326{
2327    generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
2328
2329    RefPtr<RegisterID> dstRegister = generator.newTemporary();
2330    generator.emitLoad(dstRegister.get(), jsUndefined());
2331    emitStatementsBytecode(generator, dstRegister.get());
2332
2333    generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
2334    generator.emitEnd(dstRegister.get());
2335}
2336
2337// ------------------------------ FunctionBodyNode -----------------------------
2338
2339void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2340{
2341    generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
2342    emitStatementsBytecode(generator, generator.ignoredResult());
2343
2344    StatementNode* singleStatement = this->singleStatement();
2345    ReturnNode* returnNode = 0;
2346
2347    // Check for a return statement at the end of a function composed of a single block.
2348    if (singleStatement && singleStatement->isBlock()) {
2349        StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2350        if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
2351            returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
2352    }
2353
2354    // If there is no return we must automatically insert one.
2355    if (!returnNode) {
2356        RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
2357        ASSERT(startOffset() >= lineStartOffset());
2358        generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
2359        generator.emitReturn(r0);
2360        return;
2361    }
2362
2363    // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
2364    if (static_cast<BlockNode*>(singleStatement)->singleStatement()) {
2365        ExpressionNode* returnValueExpression = returnNode->value();
2366        if (returnValueExpression && returnValueExpression->isSubtract()) {
2367            ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
2368            ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
2369            if (lhsExpression->isResolveNode()
2370                && rhsExpression->isResolveNode()
2371                && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
2372                && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
2373
2374                generator.setIsNumericCompareFunction(true);
2375            }
2376        }
2377    }
2378}
2379
2380// ------------------------------ FuncDeclNode ---------------------------------
2381
2382void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2383{
2384}
2385
2386// ------------------------------ FuncExprNode ---------------------------------
2387
2388RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2389{
2390    return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2391}
2392
2393// ------------------------------ DeconstructingAssignmentNode -----------------
2394RegisterID* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2395{
2396    if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
2397        return result;
2398    RefPtr<RegisterID> initializer = generator.tempDestination(dst);
2399    generator.emitNode(initializer.get(), m_initializer);
2400    m_bindings->bindValue(generator, initializer.get());
2401    return generator.moveToDestinationIfNeeded(dst, initializer.get());
2402}
2403
2404DeconstructionPatternNode::~DeconstructionPatternNode()
2405{
2406}
2407
2408void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
2409{
2410    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2411        auto target = m_targetPatterns[i];
2412        if (!target)
2413            continue;
2414        RefPtr<RegisterID> temp = generator.newTemporary();
2415        generator.emitLoad(temp.get(), jsNumber(i));
2416        generator.emitGetByVal(temp.get(), rhs, temp.get());
2417        target->bindValue(generator, temp.get());
2418    }
2419}
2420
2421RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
2422{
2423    if (rhs->isResolveNode()
2424        && generator.willResolveToArguments(static_cast<ResolveNode*>(rhs)->identifier())
2425        && !generator.symbolTable().slowArguments()) {
2426        for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2427            auto target = m_targetPatterns[i];
2428            if (!target)
2429                continue;
2430
2431            RefPtr<RegisterID> temp = generator.newTemporary();
2432            generator.emitLoad(temp.get(), jsNumber(i));
2433            generator.emitGetArgumentByVal(temp.get(), generator.uncheckedRegisterForArguments(), temp.get());
2434            target->bindValue(generator, temp.get());
2435        }
2436        if (dst == generator.ignoredResult() || !dst)
2437            return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
2438        Local local = generator.local(generator.vm()->propertyNames->arguments);
2439        return generator.moveToDestinationIfNeeded(dst, local.get());
2440    }
2441    if (!rhs->isSimpleArray())
2442        return 0;
2443
2444    RefPtr<RegisterID> resultRegister;
2445    if (dst && dst != generator.ignoredResult())
2446        resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
2447    ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
2448    Vector<ExpressionNode*> elements;
2449    for (; elementNodes; elementNodes = elementNodes->next())
2450        elements.append(elementNodes->value());
2451    if (m_targetPatterns.size() != elements.size())
2452        return 0;
2453    Vector<RefPtr<RegisterID>> registers;
2454    registers.reserveCapacity(m_targetPatterns.size());
2455    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2456        registers.uncheckedAppend(generator.newTemporary());
2457        generator.emitNode(registers.last().get(), elements[i]);
2458        if (resultRegister)
2459            generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
2460    }
2461
2462    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2463        if (m_targetPatterns[i])
2464            m_targetPatterns[i]->bindValue(generator, registers[i].get());
2465    }
2466    if (resultRegister)
2467        return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
2468    return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
2469}
2470
2471void ArrayPatternNode::toString(StringBuilder& builder) const
2472{
2473    builder.append('[');
2474    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2475        if (!m_targetPatterns[i]) {
2476            builder.append(',');
2477            continue;
2478        }
2479        m_targetPatterns[i]->toString(builder);
2480        if (i < m_targetPatterns.size() - 1)
2481            builder.append(',');
2482    }
2483    builder.append(']');
2484}
2485
2486void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2487{
2488    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2489        if (DeconstructionPatternNode* node = m_targetPatterns[i].get())
2490            node->collectBoundIdentifiers(identifiers);
2491    }
2492}
2493
2494void ObjectPatternNode::toString(StringBuilder& builder) const
2495{
2496    builder.append('{');
2497    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2498        if (m_targetPatterns[i].wasString) {
2499            builder.append('"');
2500            escapeStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
2501            builder.append('"');
2502        } else
2503            builder.append(m_targetPatterns[i].propertyName.string());
2504        builder.append(":");
2505        m_targetPatterns[i].pattern->toString(builder);
2506        if (i < m_targetPatterns.size() - 1)
2507            builder.append(',');
2508    }
2509    builder.append('}');
2510}
2511
2512void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
2513{
2514    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2515        auto& target = m_targetPatterns[i];
2516        RefPtr<RegisterID> temp = generator.newTemporary();
2517        generator.emitGetById(temp.get(), rhs, target.propertyName);
2518        target.pattern->bindValue(generator, temp.get());
2519    }
2520}
2521
2522void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2523{
2524    for (size_t i = 0; i < m_targetPatterns.size(); i++)
2525        m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
2526}
2527
2528void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
2529{
2530    if (Local local = generator.local(m_boundProperty)) {
2531        if (local.isReadOnly()) {
2532            generator.emitReadOnlyExceptionIfNeeded();
2533            return;
2534        }
2535        generator.emitMove(local.get(), value);
2536        return;
2537    }
2538    if (generator.isStrictMode())
2539        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
2540    RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty);
2541    generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
2542    generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
2543    return;
2544}
2545
2546void BindingNode::toString(StringBuilder& builder) const
2547{
2548    builder.append(m_boundProperty.string());
2549}
2550
2551void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2552{
2553    identifiers.append(m_boundProperty);
2554}
2555
2556RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2557{
2558    RELEASE_ASSERT_NOT_REACHED();
2559    return 0;
2560}
2561
2562} // namespace JSC
2563