Ignore:
Timestamp:
Dec 8, 2009, 5:29:52 PM (15 years ago)
Author:
[email protected]
Message:

move code generation portions of Nodes.cpp to bytecompiler directory
https://bugs.webkit.org/show_bug.cgi?id=32284

Reviewed by Darin Adler.

  • bytecompiler/NodesCodegen.cpp: Copied from parser/Nodes.cpp. Removed parts that

are not about codegen.

  • parser/Nodes.cpp: Removed everything that is about codegen.

Update build systems:

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/parser/Nodes.cpp

    r51735 r51882  
    5050namespace JSC {
    5151
    52 /*
    53     Details of the emitBytecode function.
    54 
    55     Return value: The register holding the production's value.
    56              dst: An optional parameter specifying the most efficient destination at
    57                   which to store the production's value. The callee must honor dst.
    58 
    59     The dst argument provides for a crude form of copy propagation. For example,
    60 
    61         x = 1
    62 
    63     becomes
    64    
    65         load r[x], 1
    66    
    67     instead of
    68 
    69         load r0, 1
    70         mov r[x], r0
    71    
    72     because the assignment node, "x =", passes r[x] as dst to the number node, "1".
    73 */
    74 
    75 // ------------------------------ ThrowableExpressionData --------------------------------
    76 
    77 static void substitute(UString& string, const UString& substring)
    78 {
    79     int position = string.find("%s");
    80     ASSERT(position != -1);
    81     UString newString = string.substr(0, position);
    82     newString.append(substring);
    83     newString.append(string.substr(position + 2));
    84     string = newString;
    85 }
    86 
    87 RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message)
    88 {
    89     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    90     RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
    91     generator.emitThrow(exception);
    92     return exception;
    93 }
    94 
    95 RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label)
    96 {
    97     UString message = messageTemplate;
    98     substitute(message, label);
    99     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    100     RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
    101     generator.emitThrow(exception);
    102     return exception;
    103 }
    104 
    105 inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label)
    106 {
    107     return emitThrowError(generator, type, messageTemplate, label.ustring());
    108 }
    10952
    11053// ------------------------------ StatementNode --------------------------------
     
    12972    size_t size = m_statements.size();
    13073    return size == 1 ? m_statements[0] : 0;
    131 }
    132 
    133 inline StatementNode* SourceElements::lastStatement() const
    134 {
    135     size_t size = m_statements.size();
    136     return size ? m_statements[size - 1] : 0;
    137 }
    138 
    139 // ------------------------------ NullNode -------------------------------------
    140 
    141 RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    142 {
    143     if (dst == generator.ignoredResult())
    144         return 0;
    145     return generator.emitLoad(dst, jsNull());
    146 }
    147 
    148 // ------------------------------ BooleanNode ----------------------------------
    149 
    150 RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    151 {
    152     if (dst == generator.ignoredResult())
    153         return 0;
    154     return generator.emitLoad(dst, m_value);
    155 }
    156 
    157 // ------------------------------ NumberNode -----------------------------------
    158 
    159 RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    160 {
    161     if (dst == generator.ignoredResult())
    162         return 0;
    163     return generator.emitLoad(dst, m_value);
    164 }
    165 
    166 // ------------------------------ StringNode -----------------------------------
    167 
    168 RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    169 {
    170     if (dst == generator.ignoredResult())
    171         return 0;
    172     return generator.emitLoad(dst, m_value);
    173 }
    174 
    175 // ------------------------------ RegExpNode -----------------------------------
    176 
    177 RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    178 {
    179     RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
    180     if (!regExp->isValid())
    181         return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage());
    182     if (dst == generator.ignoredResult())
    183         return 0;
    184     return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
    185 }
    186 
    187 // ------------------------------ ThisNode -------------------------------------
    188 
    189 RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    190 {
    191     if (dst == generator.ignoredResult())
    192         return 0;
    193     return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
    194 }
    195 
    196 // ------------------------------ ResolveNode ----------------------------------
    197 
    198 bool ResolveNode::isPure(BytecodeGenerator& generator) const
    199 {
    200     return generator.isLocal(m_ident);
    201 }
    202 
    203 RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    204 {
    205     if (RegisterID* local = generator.registerFor(m_ident)) {
    206         if (dst == generator.ignoredResult())
    207             return 0;
    208         return generator.moveToDestinationIfNeeded(dst, local);
    209     }
    210    
    211     generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
    212     return generator.emitResolve(generator.finalDestination(dst), m_ident);
    213 }
    214 
    215 // ------------------------------ ArrayNode ------------------------------------
    216 
    217 RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    218 {
    219     // FIXME: Should we put all of this code into emitNewArray?
    220 
    221     unsigned length = 0;
    222     ElementNode* firstPutElement;
    223     for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
    224         if (firstPutElement->elision())
    225             break;
    226         ++length;
    227     }
    228 
    229     if (!firstPutElement && !m_elision)
    230         return generator.emitNewArray(generator.finalDestination(dst), m_element);
    231 
    232     RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element);
    233 
    234     for (ElementNode* n = firstPutElement; n; n = n->next()) {
    235         RegisterID* value = generator.emitNode(n->value());
    236         length += n->elision();
    237         generator.emitPutByIndex(array.get(), length++, value);
    238     }
    239 
    240     if (m_elision) {
    241         RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
    242         generator.emitPutById(array.get(), generator.propertyNames().length, value);
    243     }
    244 
    245     return generator.moveToDestinationIfNeeded(dst, array.get());
    246 }
    247 
    248 bool ArrayNode::isSimpleArray() const
    249 {
    250     if (m_elision || m_optional)
    251         return false;
    252     for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
    253         if (ptr->elision())
    254             return false;
    255     }
    256     return true;
    257 }
    258 
    259 ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const
    260 {
    261     ASSERT(!m_elision && !m_optional);
    262     ElementNode* ptr = m_element;
    263     if (!ptr)
    264         return 0;
    265     ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value());
    266     ArgumentListNode* tail = head;
    267     ptr = ptr->next();
    268     for (; ptr; ptr = ptr->next()) {
    269         ASSERT(!ptr->elision());
    270         tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value());
    271     }
    272     return head;
    273 }
    274 
    275 // ------------------------------ ObjectLiteralNode ----------------------------
    276 
    277 RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    278 {
    279      if (!m_list) {
    280          if (dst == generator.ignoredResult())
    281              return 0;
    282          return generator.emitNewObject(generator.finalDestination(dst));
    283      }
    284      return generator.emitNode(dst, m_list);
    285 }
    286 
    287 // ------------------------------ PropertyListNode -----------------------------
    288 
    289 RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    290 {
    291     RefPtr<RegisterID> newObj = generator.tempDestination(dst);
    292    
    293     generator.emitNewObject(newObj.get());
    294    
    295     for (PropertyListNode* p = this; p; p = p->m_next) {
    296         RegisterID* value = generator.emitNode(p->m_node->m_assign);
    297        
    298         switch (p->m_node->m_type) {
    299             case PropertyNode::Constant: {
    300                 generator.emitPutById(newObj.get(), p->m_node->name(), value);
    301                 break;
    302             }
    303             case PropertyNode::Getter: {
    304                 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
    305                 break;
    306             }
    307             case PropertyNode::Setter: {
    308                 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
    309                 break;
    310             }
    311             default:
    312                 ASSERT_NOT_REACHED();
    313         }
    314     }
    315    
    316     return generator.moveToDestinationIfNeeded(dst, newObj.get());
    317 }
    318 
    319 // ------------------------------ BracketAccessorNode --------------------------------
    320 
    321 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    322 {
    323     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
    324     RegisterID* property = generator.emitNode(m_subscript);
    325     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    326     return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
    327 }
    328 
    329 // ------------------------------ DotAccessorNode --------------------------------
    330 
    331 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    332 {
    333     RegisterID* base = generator.emitNode(m_base);
    334     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    335     return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
    336 }
    337 
    338 // ------------------------------ ArgumentListNode -----------------------------
    339 
    340 RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    341 {
    342     ASSERT(m_expr);
    343     return generator.emitNode(dst, m_expr);
    344 }
    345 
    346 // ------------------------------ NewExprNode ----------------------------------
    347 
    348 RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    349 {
    350     RefPtr<RegisterID> func = generator.emitNode(m_expr);
    351     return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset());
    352 }
    353 
    354 // ------------------------------ EvalFunctionCallNode ----------------------------------
    355 
    356 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    357 {
    358     RefPtr<RegisterID> func = generator.tempDestination(dst);
    359     RefPtr<RegisterID> thisRegister = generator.newTemporary();
    360     generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
    361     generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
    362     return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    363 }
    364 
    365 // ------------------------------ FunctionCallValueNode ----------------------------------
    366 
    367 RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    368 {
    369     RefPtr<RegisterID> func = generator.emitNode(m_expr);
    370     RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
    371     return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    372 }
    373 
    374 // ------------------------------ FunctionCallResolveNode ----------------------------------
    375 
    376 RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    377 {
    378     if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
    379         RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
    380         return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    381     }
    382 
    383     int index = 0;
    384     size_t depth = 0;
    385     JSObject* globalObject = 0;
    386     if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
    387         RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
    388         RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
    389         return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    390     }
    391 
    392     RefPtr<RegisterID> func = generator.newTemporary();
    393     RefPtr<RegisterID> thisRegister = generator.newTemporary();
    394     int identifierStart = divot() - startOffset();
    395     generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
    396     generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident);
    397     return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    398 }
    399 
    400 // ------------------------------ FunctionCallBracketNode ----------------------------------
    401 
    402 RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    403 {
    404     RefPtr<RegisterID> base = generator.emitNode(m_base);
    405     RegisterID* property = generator.emitNode(m_subscript);
    406     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    407     RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
    408     RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
    409     return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    410 }
    411 
    412 // ------------------------------ FunctionCallDotNode ----------------------------------
    413 
    414 RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    415 {
    416     RefPtr<RegisterID> function = generator.tempDestination(dst);
    417     RefPtr<RegisterID> thisRegister = generator.newTemporary();
    418     generator.emitNode(thisRegister.get(), m_base);
    419     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    420     generator.emitMethodCheck();
    421     generator.emitGetById(function.get(), thisRegister.get(), m_ident);
    422     return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    423 }
    424 
    425 RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    426 {
    427     RefPtr<Label> realCall = generator.newLabel();
    428     RefPtr<Label> end = generator.newLabel();
    429     RefPtr<RegisterID> base = generator.emitNode(m_base);
    430     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    431     RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    432     RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
    433     generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
    434     {
    435         RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
    436         RefPtr<RegisterID> thisRegister = generator.newTemporary();
    437         ArgumentListNode* oldList = m_args->m_listNode;
    438         if (m_args->m_listNode && m_args->m_listNode->m_expr) {
    439             generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
    440             m_args->m_listNode = m_args->m_listNode->m_next;
    441         } else
    442             generator.emitLoad(thisRegister.get(), jsNull());
    443 
    444         generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    445         generator.emitJump(end.get());
    446         m_args->m_listNode = oldList;
    447     }
    448     generator.emitLabel(realCall.get());
    449     {
    450         RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
    451         generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    452     }
    453     generator.emitLabel(end.get());
    454     return finalDestination.get();
    455 }
    456    
    457 static bool areTrivialApplyArguments(ArgumentsNode* args)
    458 {
    459     return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
    460         || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
    461 }
    462 
    463 RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    464 {
    465     // A few simple cases can be trivially handled as ordinary function calls.
    466     // function.apply(), function.apply(arg) -> identical to function.call
    467     // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
    468     bool mayBeCall = areTrivialApplyArguments(m_args);
    469 
    470     RefPtr<Label> realCall = generator.newLabel();
    471     RefPtr<Label> end = generator.newLabel();
    472     RefPtr<RegisterID> base = generator.emitNode(m_base);
    473     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    474     RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    475     RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
    476     generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
    477     {
    478         if (mayBeCall) {
    479             RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
    480             RefPtr<RegisterID> thisRegister = generator.newTemporary();
    481             ArgumentListNode* oldList = m_args->m_listNode;
    482             if (m_args->m_listNode && m_args->m_listNode->m_expr) {
    483                 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
    484                 m_args->m_listNode = m_args->m_listNode->m_next;
    485                 if (m_args->m_listNode) {
    486                     ASSERT(m_args->m_listNode->m_expr->isSimpleArray());
    487                     ASSERT(!m_args->m_listNode->m_next);
    488                     m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData());
    489                 }
    490             } else
    491                 generator.emitLoad(thisRegister.get(), jsNull());
    492             generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    493             m_args->m_listNode = oldList;
    494         } else {
    495             ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
    496             RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
    497             RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
    498             RefPtr<RegisterID> thisRegister = generator.newTemporary();
    499             RefPtr<RegisterID> argsRegister = generator.newTemporary();
    500             generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
    501             ArgumentListNode* args = m_args->m_listNode->m_next;
    502             bool isArgumentsApply = false;
    503             if (args->m_expr->isResolveNode()) {
    504                 ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr);
    505                 isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier());
    506                 if (isArgumentsApply)
    507                     generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments());
    508             }
    509             if (!isArgumentsApply)
    510                 generator.emitNode(argsRegister.get(), args->m_expr);
    511             while ((args = args->m_next))
    512                 generator.emitNode(args->m_expr);
    513 
    514             generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
    515             generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
    516         }
    517         generator.emitJump(end.get());
    518     }
    519     generator.emitLabel(realCall.get());
    520     {
    521         RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
    522         generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
    523     }
    524     generator.emitLabel(end.get());
    525     return finalDestination.get();
    526 }
    527 
    528 // ------------------------------ PostfixResolveNode ----------------------------------
    529 
    530 static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
    531 {
    532     return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
    533 }
    534 
    535 static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
    536 {
    537     if (srcDst == dst)
    538         return generator.emitToJSNumber(dst, srcDst);
    539     return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
    540 }
    541 
    542 RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    543 {
    544     if (RegisterID* local = generator.registerFor(m_ident)) {
    545         if (generator.isLocalConstant(m_ident)) {
    546             if (dst == generator.ignoredResult())
    547                 return 0;
    548             return generator.emitToJSNumber(generator.finalDestination(dst), local);
    549         }
    550 
    551         if (dst == generator.ignoredResult())
    552             return emitPreIncOrDec(generator, local, m_operator);
    553         return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
    554     }
    555 
    556     int index = 0;
    557     size_t depth = 0;
    558     JSObject* globalObject = 0;
    559     if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
    560         RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
    561         RegisterID* oldValue;
    562         if (dst == generator.ignoredResult()) {
    563             oldValue = 0;
    564             emitPreIncOrDec(generator, value.get(), m_operator);
    565         } else {
    566             oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
    567         }
    568         generator.emitPutScopedVar(depth, index, value.get(), globalObject);
    569         return oldValue;
    570     }
    571 
    572     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    573     RefPtr<RegisterID> value = generator.newTemporary();
    574     RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
    575     RegisterID* oldValue;
    576     if (dst == generator.ignoredResult()) {
    577         oldValue = 0;
    578         emitPreIncOrDec(generator, value.get(), m_operator);
    579     } else {
    580         oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
    581     }
    582     generator.emitPutById(base.get(), m_ident, value.get());
    583     return oldValue;
    584 }
    585 
    586 // ------------------------------ PostfixBracketNode ----------------------------------
    587 
    588 RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    589 {
    590     RefPtr<RegisterID> base = generator.emitNode(m_base);
    591     RefPtr<RegisterID> property = generator.emitNode(m_subscript);
    592 
    593     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    594     RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
    595     RegisterID* oldValue;
    596     if (dst == generator.ignoredResult()) {
    597         oldValue = 0;
    598         if (m_operator == OpPlusPlus)
    599             generator.emitPreInc(value.get());
    600         else
    601             generator.emitPreDec(value.get());
    602     } else {
    603         oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
    604     }
    605     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    606     generator.emitPutByVal(base.get(), property.get(), value.get());
    607     return oldValue;
    608 }
    609 
    610 // ------------------------------ PostfixDotNode ----------------------------------
    611 
    612 RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    613 {
    614     RefPtr<RegisterID> base = generator.emitNode(m_base);
    615 
    616     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    617     RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
    618     RegisterID* oldValue;
    619     if (dst == generator.ignoredResult()) {
    620         oldValue = 0;
    621         if (m_operator == OpPlusPlus)
    622             generator.emitPreInc(value.get());
    623         else
    624             generator.emitPreDec(value.get());
    625     } else {
    626         oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
    627     }
    628     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    629     generator.emitPutById(base.get(), m_ident, value.get());
    630     return oldValue;
    631 }
    632 
    633 // ------------------------------ PostfixErrorNode -----------------------------------
    634 
    635 RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    636 {
    637     return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
    638         ? "Postfix ++ operator applied to value that is not a reference."
    639         : "Postfix -- operator applied to value that is not a reference.");
    640 }
    641 
    642 // ------------------------------ DeleteResolveNode -----------------------------------
    643 
    644 RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    645 {
    646     if (generator.registerFor(m_ident))
    647         return generator.emitLoad(generator.finalDestination(dst), false);
    648 
    649     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    650     RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
    651     return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
    652 }
    653 
    654 // ------------------------------ DeleteBracketNode -----------------------------------
    655 
    656 RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    657 {
    658     RefPtr<RegisterID> r0 = generator.emitNode(m_base);
    659     RegisterID* r1 = generator.emitNode(m_subscript);
    660 
    661     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    662     return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
    663 }
    664 
    665 // ------------------------------ DeleteDotNode -----------------------------------
    666 
    667 RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    668 {
    669     RegisterID* r0 = generator.emitNode(m_base);
    670 
    671     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    672     return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
    673 }
    674 
    675 // ------------------------------ DeleteValueNode -----------------------------------
    676 
    677 RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    678 {
    679     generator.emitNode(generator.ignoredResult(), m_expr);
    680 
    681     // delete on a non-location expression ignores the value and returns true
    682     return generator.emitLoad(generator.finalDestination(dst), true);
    683 }
    684 
    685 // ------------------------------ VoidNode -------------------------------------
    686 
    687 RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    688 {
    689     if (dst == generator.ignoredResult()) {
    690         generator.emitNode(generator.ignoredResult(), m_expr);
    691         return 0;
    692     }
    693     RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
    694     return generator.emitLoad(dst, jsUndefined());
    695 }
    696 
    697 // ------------------------------ TypeOfValueNode -----------------------------------
    698 
    699 RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    700 {
    701     if (RegisterID* local = generator.registerFor(m_ident)) {
    702         if (dst == generator.ignoredResult())
    703             return 0;
    704         return generator.emitTypeOf(generator.finalDestination(dst), local);
    705     }
    706 
    707     RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
    708     generator.emitGetById(scratch.get(), scratch.get(), m_ident);
    709     if (dst == generator.ignoredResult())
    710         return 0;
    711     return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
    712 }
    713 
    714 // ------------------------------ TypeOfValueNode -----------------------------------
    715 
    716 RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    717 {
    718     if (dst == generator.ignoredResult()) {
    719         generator.emitNode(generator.ignoredResult(), m_expr);
    720         return 0;
    721     }
    722     RefPtr<RegisterID> src = generator.emitNode(m_expr);
    723     return generator.emitTypeOf(generator.finalDestination(dst), src.get());
    724 }
    725 
    726 // ------------------------------ PrefixResolveNode ----------------------------------
    727 
    728 RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    729 {
    730     if (RegisterID* local = generator.registerFor(m_ident)) {
    731         if (generator.isLocalConstant(m_ident)) {
    732             if (dst == generator.ignoredResult())
    733                 return 0;
    734             RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
    735             return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
    736         }
    737 
    738         emitPreIncOrDec(generator, local, m_operator);
    739         return generator.moveToDestinationIfNeeded(dst, local);
    740     }
    741 
    742     int index = 0;
    743     size_t depth = 0;
    744     JSObject* globalObject = 0;
    745     if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
    746         RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
    747         emitPreIncOrDec(generator, propDst.get(), m_operator);
    748         generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
    749         return generator.moveToDestinationIfNeeded(dst, propDst.get());
    750     }
    751 
    752     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    753     RefPtr<RegisterID> propDst = generator.tempDestination(dst);
    754     RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
    755     emitPreIncOrDec(generator, propDst.get(), m_operator);
    756     generator.emitPutById(base.get(), m_ident, propDst.get());
    757     return generator.moveToDestinationIfNeeded(dst, propDst.get());
    758 }
    759 
    760 // ------------------------------ PrefixBracketNode ----------------------------------
    761 
    762 RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    763 {
    764     RefPtr<RegisterID> base = generator.emitNode(m_base);
    765     RefPtr<RegisterID> property = generator.emitNode(m_subscript);
    766     RefPtr<RegisterID> propDst = generator.tempDestination(dst);
    767 
    768     generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
    769     RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
    770     if (m_operator == OpPlusPlus)
    771         generator.emitPreInc(value);
    772     else
    773         generator.emitPreDec(value);
    774     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    775     generator.emitPutByVal(base.get(), property.get(), value);
    776     return generator.moveToDestinationIfNeeded(dst, propDst.get());
    777 }
    778 
    779 // ------------------------------ PrefixDotNode ----------------------------------
    780 
    781 RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    782 {
    783     RefPtr<RegisterID> base = generator.emitNode(m_base);
    784     RefPtr<RegisterID> propDst = generator.tempDestination(dst);
    785 
    786     generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
    787     RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
    788     if (m_operator == OpPlusPlus)
    789         generator.emitPreInc(value);
    790     else
    791         generator.emitPreDec(value);
    792     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    793     generator.emitPutById(base.get(), m_ident, value);
    794     return generator.moveToDestinationIfNeeded(dst, propDst.get());
    795 }
    796 
    797 // ------------------------------ PrefixErrorNode -----------------------------------
    798 
    799 RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    800 {
    801     return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
    802         ? "Prefix ++ operator applied to value that is not a reference."
    803         : "Prefix -- operator applied to value that is not a reference.");
    804 }
    805 
    806 // ------------------------------ Unary Operation Nodes -----------------------------------
    807 
    808 RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    809 {
    810     RegisterID* src = generator.emitNode(m_expr);
    811     return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
    812 }
    813 
    814 
    815 // ------------------------------ LogicalNotNode -----------------------------------
    816 
    817 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
    818 {
    819     ASSERT(expr()->hasConditionContextCodegen());
    820 
    821     // reverse the true and false targets
    822     generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue);
    823 }
    824 
    825 
    826 // ------------------------------ Binary Operation Nodes -----------------------------------
    827 
    828 // BinaryOpNode::emitStrcat:
    829 //
    830 // This node generates an op_strcat operation.  This opcode can handle concatenation of three or
    831 // more values, where we can determine a set of separate op_add operations would be operating on
    832 // string values.
    833 //
    834 // This function expects to be operating on a graph of AST nodes looking something like this:
    835 //
    836 //     (a)...     (b)
    837 //          \   /
    838 //           (+)     (c)
    839 //              \   /
    840 //      [d]     ((+))
    841 //         \    /
    842 //          [+=]
    843 //
    844 // The assignment operation is optional, if it exists the register holding the value on the
    845 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
    846 //
    847 // The method should be called on the node at the root of the tree of regular binary add
    848 // operations (marked in the diagram with a double set of parentheses).  This node must
    849 // be performing a string concatenation (determined by statically detecting that at least
    850 // one child must be a string). 
    851 //
    852 // Since the minimum number of values being concatenated together is expected to be 3, if
    853 // a lhs to a concatenating assignment is not provided then the  root add should have at
    854 // least one left child that is also an add that can be determined to be operating on strings.
    855 //
    856 RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
    857 {
    858     ASSERT(isAdd());
    859     ASSERT(resultDescriptor().definitelyIsString());
    860 
    861     // Create a list of expressions for all the adds in the tree of nodes we can convert into
    862     // a string concatenation.  The rightmost node (c) is added first.  The rightmost node is
    863     // added first, and the leftmost child is never added, so the vector produced for the
    864     // example above will be [ c, b ].
    865     Vector<ExpressionNode*, 16> reverseExpressionList;
    866     reverseExpressionList.append(m_expr2);
    867 
    868     // Examine the left child of the add.  So long as this is a string add, add its right-child
    869     // to the list, and keep processing along the left fork.
    870     ExpressionNode* leftMostAddChild = m_expr1;
    871     while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
    872         reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
    873         leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
    874     }
    875 
    876     Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
    877 
    878     // If there is an assignment, allocate a temporary to hold the lhs after conversion.
    879     // We could possibly avoid this (the lhs is converted last anyway, we could let the
    880     // op_strcat node handle its conversion if required).
    881     if (lhs)
    882         temporaryRegisters.append(generator.newTemporary());
    883 
    884     // Emit code for the leftmost node ((a) in the example).
    885     temporaryRegisters.append(generator.newTemporary());
    886     RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
    887     generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
    888 
    889     // Note on ordering of conversions:
    890     //
    891     // We maintain the same ordering of conversions as we would see if the concatenations
    892     // was performed as a sequence of adds (otherwise this optimization could change
    893     // behaviour should an object have been provided a valueOf or toString method).
    894     //
    895     // Considering the above example, the sequnce of execution is:
    896     //     * evaluate operand (a)
    897     //     * evaluate operand (b)
    898     //     * convert (a) to primitive   <-  (this would be triggered by the first add)
    899     //     * convert (b) to primitive   <-  (ditto)
    900     //     * evaluate operand (c)
    901     //     * convert (c) to primitive   <-  (this would be triggered by the second add)
    902     // And optionally, if there is an assignment:
    903     //     * convert (d) to primitive   <-  (this would be triggered by the assigning addition)
    904     //
    905     // As such we do not plant an op to convert the leftmost child now.  Instead, use
    906     // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
    907     // once the second node has been generated.  However, if the leftmost child is an
    908     // immediate we can trivially determine that no conversion will be required.
    909     // If this is the case
    910     if (leftMostAddChild->isString())
    911         leftMostAddChildTempRegister = 0;
    912 
    913     while (reverseExpressionList.size()) {
    914         ExpressionNode* node = reverseExpressionList.last();
    915         reverseExpressionList.removeLast();
    916 
    917         // Emit the code for the current node.
    918         temporaryRegisters.append(generator.newTemporary());
    919         generator.emitNode(temporaryRegisters.last().get(), node);
    920 
    921         // On the first iteration of this loop, when we first reach this point we have just
    922         // generated the second node, which means it is time to convert the leftmost operand.
    923         if (leftMostAddChildTempRegister) {
    924             generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
    925             leftMostAddChildTempRegister = 0; // Only do this once.
    926         }
    927         // Plant a conversion for this node, if necessary.
    928         if (!node->isString())
    929             generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
    930     }
    931     ASSERT(temporaryRegisters.size() >= 3);
    932 
    933     // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
    934     // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
    935     if (emitExpressionInfoForMe)
    936         generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
    937 
    938     // If there is an assignment convert the lhs now.  This will also copy lhs to
    939     // the temporary register we allocated for it.
    940     if (lhs)
    941         generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
    942 
    943     return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
    944 }
    945 
    946 RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    947 {
    948     OpcodeID opcodeID = this->opcodeID();
    949 
    950     if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString())
    951         return emitStrcat(generator, dst);
    952 
    953     if (opcodeID == op_neq) {
    954         if (m_expr1->isNull() || m_expr2->isNull()) {
    955             RefPtr<RegisterID> src = generator.tempDestination(dst);
    956             generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
    957             return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
    958         }
    959     }
    960 
    961     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    962     RegisterID* src2 = generator.emitNode(m_expr2);
    963     return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
    964 }
    965 
    966 RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    967 {
    968     if (m_expr1->isNull() || m_expr2->isNull()) {
    969         RefPtr<RegisterID> src = generator.tempDestination(dst);
    970         generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
    971         return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
    972     }
    973 
    974     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    975     RegisterID* src2 = generator.emitNode(m_expr2);
    976     return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
    977 }
    978 
    979 RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    980 {
    981     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    982     RegisterID* src2 = generator.emitNode(m_expr2);
    983     return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
    984 }
    985 
    986 RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    987 {
    988     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    989     RegisterID* src2 = generator.emitNode(m_expr2);
    990     return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
    991 }
    992 
    993 RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    994 {
    995     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    996     RegisterID* src2 = generator.emitNode(m_expr2);
    997     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    998     return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
    999 }
    1000 
    1001 RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1002 {
    1003     RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    1004     RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
    1005 
    1006     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1007     generator.emitGetByIdExceptionInfo(op_instanceof);
    1008     RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
    1009 
    1010     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1011     return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
    1012 }
    1013 
    1014 // ------------------------------ LogicalOpNode ----------------------------
    1015 
    1016 RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1017 {
    1018     RefPtr<RegisterID> temp = generator.tempDestination(dst);
    1019     RefPtr<Label> target = generator.newLabel();
    1020    
    1021     generator.emitNode(temp.get(), m_expr1);
    1022     if (m_operator == OpLogicalAnd)
    1023         generator.emitJumpIfFalse(temp.get(), target.get());
    1024     else
    1025         generator.emitJumpIfTrue(temp.get(), target.get());
    1026     generator.emitNode(temp.get(), m_expr2);
    1027     generator.emitLabel(target.get());
    1028 
    1029     return generator.moveToDestinationIfNeeded(dst, temp.get());
    1030 }
    1031 
    1032 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
    1033 {
    1034     if (m_expr1->hasConditionContextCodegen()) {
    1035         RefPtr<Label> afterExpr1 = generator.newLabel();
    1036         if (m_operator == OpLogicalAnd)
    1037             generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, true);
    1038         else
    1039             generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), false);
    1040         generator.emitLabel(afterExpr1.get());
    1041     } else {
    1042         RegisterID* temp = generator.emitNode(m_expr1);
    1043         if (m_operator == OpLogicalAnd)
    1044             generator.emitJumpIfFalse(temp, falseTarget);
    1045         else
    1046             generator.emitJumpIfTrue(temp, trueTarget);
    1047     }
    1048 
    1049     if (m_expr2->hasConditionContextCodegen())
    1050         generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMeansTrue);
    1051     else {
    1052         RegisterID* temp = generator.emitNode(m_expr2);
    1053         if (fallThroughMeansTrue)
    1054             generator.emitJumpIfFalse(temp, falseTarget);
    1055         else
    1056             generator.emitJumpIfTrue(temp, trueTarget);
    1057     }
    1058 }
    1059 
    1060 // ------------------------------ ConditionalNode ------------------------------
    1061 
    1062 RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1063 {
    1064     RefPtr<RegisterID> newDst = generator.finalDestination(dst);
    1065     RefPtr<Label> beforeElse = generator.newLabel();
    1066     RefPtr<Label> afterElse = generator.newLabel();
    1067 
    1068     if (m_logical->hasConditionContextCodegen()) {
    1069         RefPtr<Label> beforeThen = generator.newLabel();
    1070         generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), true);
    1071         generator.emitLabel(beforeThen.get());
    1072     } else {
    1073         RegisterID* cond = generator.emitNode(m_logical);
    1074         generator.emitJumpIfFalse(cond, beforeElse.get());
    1075     }
    1076 
    1077     generator.emitNode(newDst.get(), m_expr1);
    1078     generator.emitJump(afterElse.get());
    1079 
    1080     generator.emitLabel(beforeElse.get());
    1081     generator.emitNode(newDst.get(), m_expr2);
    1082 
    1083     generator.emitLabel(afterElse.get());
    1084 
    1085     return newDst.get();
    1086 }
    1087 
    1088 // ------------------------------ ReadModifyResolveNode -----------------------------------
    1089 
    1090 // FIXME: should this be moved to be a method on BytecodeGenerator?
    1091 static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
    1092 {
    1093     OpcodeID opcodeID;
    1094     switch (oper) {
    1095         case OpMultEq:
    1096             opcodeID = op_mul;
    1097             break;
    1098         case OpDivEq:
    1099             opcodeID = op_div;
    1100             break;
    1101         case OpPlusEq:
    1102             if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
    1103                 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
    1104             opcodeID = op_add;
    1105             break;
    1106         case OpMinusEq:
    1107             opcodeID = op_sub;
    1108             break;
    1109         case OpLShift:
    1110             opcodeID = op_lshift;
    1111             break;
    1112         case OpRShift:
    1113             opcodeID = op_rshift;
    1114             break;
    1115         case OpURShift:
    1116             opcodeID = op_urshift;
    1117             break;
    1118         case OpAndEq:
    1119             opcodeID = op_bitand;
    1120             break;
    1121         case OpXOrEq:
    1122             opcodeID = op_bitxor;
    1123             break;
    1124         case OpOrEq:
    1125             opcodeID = op_bitor;
    1126             break;
    1127         case OpModEq:
    1128             opcodeID = op_mod;
    1129             break;
    1130         default:
    1131             ASSERT_NOT_REACHED();
    1132             return dst;
    1133     }
    1134 
    1135     RegisterID* src2 = generator.emitNode(m_right);
    1136 
    1137     // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
    1138     // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
    1139     if (emitExpressionInfoForMe)
    1140         generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
    1141 
    1142     return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
    1143 }
    1144 
    1145 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1146 {
    1147     if (RegisterID* local = generator.registerFor(m_ident)) {
    1148         if (generator.isLocalConstant(m_ident)) {
    1149             return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1150         }
    1151        
    1152         if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
    1153             RefPtr<RegisterID> result = generator.newTemporary();
    1154             generator.emitMove(result.get(), local);
    1155             emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1156             generator.emitMove(local, result.get());
    1157             return generator.moveToDestinationIfNeeded(dst, result.get());
    1158         }
    1159        
    1160         RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1161         return generator.moveToDestinationIfNeeded(dst, result);
    1162     }
    1163 
    1164     int index = 0;
    1165     size_t depth = 0;
    1166     JSObject* globalObject = 0;
    1167     if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
    1168         RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
    1169         RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1170         generator.emitPutScopedVar(depth, index, result, globalObject);
    1171         return result;
    1172     }
    1173 
    1174     RefPtr<RegisterID> src1 = generator.tempDestination(dst);
    1175     generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
    1176     RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
    1177     RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
    1178     return generator.emitPutById(base.get(), m_ident, result);
    1179 }
    1180 
    1181 // ------------------------------ AssignResolveNode -----------------------------------
    1182 
    1183 RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1184 {
    1185     if (RegisterID* local = generator.registerFor(m_ident)) {
    1186         if (generator.isLocalConstant(m_ident))
    1187             return generator.emitNode(dst, m_right);
    1188        
    1189         RegisterID* result = generator.emitNode(local, m_right);
    1190         return generator.moveToDestinationIfNeeded(dst, result);
    1191     }
    1192 
    1193     int index = 0;
    1194     size_t depth = 0;
    1195     JSObject* globalObject = 0;
    1196     if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
    1197         if (dst == generator.ignoredResult())
    1198             dst = 0;
    1199         RegisterID* value = generator.emitNode(dst, m_right);
    1200         generator.emitPutScopedVar(depth, index, value, globalObject);
    1201         return value;
    1202     }
    1203 
    1204     RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
    1205     if (dst == generator.ignoredResult())
    1206         dst = 0;
    1207     RegisterID* value = generator.emitNode(dst, m_right);
    1208     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1209     return generator.emitPutById(base.get(), m_ident, value);
    1210 }
    1211 
    1212 // ------------------------------ AssignDotNode -----------------------------------
    1213 
    1214 RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1215 {
    1216     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
    1217     RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
    1218     RegisterID* result = generator.emitNode(value.get(), m_right);
    1219     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1220     generator.emitPutById(base.get(), m_ident, result);
    1221     return generator.moveToDestinationIfNeeded(dst, result);
    1222 }
    1223 
    1224 // ------------------------------ ReadModifyDotNode -----------------------------------
    1225 
    1226 RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1227 {
    1228     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
    1229 
    1230     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    1231     RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
    1232     RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1233 
    1234     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1235     return generator.emitPutById(base.get(), m_ident, updatedValue);
    1236 }
    1237 
    1238 // ------------------------------ AssignErrorNode -----------------------------------
    1239 
    1240 RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    1241 {
    1242     return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
    1243 }
    1244 
    1245 // ------------------------------ AssignBracketNode -----------------------------------
    1246 
    1247 RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1248 {
    1249     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
    1250     RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
    1251     RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
    1252     RegisterID* result = generator.emitNode(value.get(), m_right);
    1253 
    1254     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1255     generator.emitPutByVal(base.get(), property.get(), result);
    1256     return generator.moveToDestinationIfNeeded(dst, result);
    1257 }
    1258 
    1259 // ------------------------------ ReadModifyBracketNode -----------------------------------
    1260 
    1261 RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1262 {
    1263     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
    1264     RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
    1265 
    1266     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    1267     RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
    1268     RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1269 
    1270     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1271     generator.emitPutByVal(base.get(), property.get(), updatedValue);
    1272 
    1273     return updatedValue;
    1274 }
    1275 
    1276 // ------------------------------ CommaNode ------------------------------------
    1277 
    1278 RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1279 {
    1280     ASSERT(m_expressions.size() > 1);
    1281     for (size_t i = 0; i < m_expressions.size() - 1; i++)
    1282         generator.emitNode(generator.ignoredResult(), m_expressions[i]);
    1283     return generator.emitNode(dst, m_expressions.last());
    1284 }
    1285 
    1286 // ------------------------------ ConstDeclNode ------------------------------------
    1287 
    1288 RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
    1289 {
    1290     if (RegisterID* local = generator.constRegisterFor(m_ident)) {
    1291         if (!m_init)
    1292             return local;
    1293 
    1294         return generator.emitNode(local, m_init);
    1295     }
    1296 
    1297     if (generator.codeType() != EvalCode) {
    1298         if (m_init)
    1299             return generator.emitNode(m_init);
    1300         else
    1301             return generator.emitResolve(generator.newTemporary(), m_ident);
    1302     }
    1303     // FIXME: While this code should only be hit in eval code, it will potentially
    1304     // assign to the wrong base if m_ident exists in an intervening dynamic scope.
    1305     RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
    1306     RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
    1307     return generator.emitPutById(base.get(), m_ident, value);
    1308 }
    1309 
    1310 RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    1311 {
    1312     RegisterID* result = 0;
    1313     for (ConstDeclNode* n = this; n; n = n->m_next)
    1314         result = n->emitCodeSingle(generator);
    1315 
    1316     return result;
    1317 }
    1318 
    1319 // ------------------------------ ConstStatementNode -----------------------------
    1320 
    1321 RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    1322 {
    1323     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1324     return generator.emitNode(m_next);
    1325 }
    1326 
    1327 // ------------------------------ SourceElements -------------------------------
    1328 
    1329 inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1330 {
    1331     size_t size = m_statements.size();
    1332     for (size_t i = 0; i < size; ++i)
    1333         generator.emitNode(dst, m_statements[i]);
    1334 }
    1335 
    1336 // ------------------------------ BlockNode ------------------------------------
    1337 
    1338 inline StatementNode* BlockNode::lastStatement() const
    1339 {
    1340     return m_statements ? m_statements->lastStatement() : 0;
    1341 }
    1342 
    1343 RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1344 {
    1345     if (m_statements)
    1346         m_statements->emitBytecode(generator, dst);
    1347     return 0;
    1348 }
    1349 
    1350 // ------------------------------ EmptyStatementNode ---------------------------
    1351 
    1352 RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1353 {
    1354     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1355     return dst;
    1356 }
    1357 
    1358 // ------------------------------ DebuggerStatementNode ---------------------------
    1359 
    1360 RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1361 {
    1362     generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
    1363     return dst;
    1364 }
    1365 
    1366 // ------------------------------ ExprStatementNode ----------------------------
    1367 
    1368 RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1369 {
    1370     ASSERT(m_expr);
    1371     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1372     return generator.emitNode(dst, m_expr);
    1373 }
    1374 
    1375 // ------------------------------ VarStatementNode ----------------------------
    1376 
    1377 RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    1378 {
    1379     ASSERT(m_expr);
    1380     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1381     return generator.emitNode(m_expr);
    1382 }
    1383 
    1384 // ------------------------------ IfNode ---------------------------------------
    1385 
    1386 RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1387 {
    1388     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1389    
    1390     RefPtr<Label> afterThen = generator.newLabel();
    1391 
    1392     if (m_condition->hasConditionContextCodegen()) {
    1393         RefPtr<Label> beforeThen = generator.newLabel();
    1394         generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), true);
    1395         generator.emitLabel(beforeThen.get());
    1396     } else {
    1397         RegisterID* cond = generator.emitNode(m_condition);
    1398         generator.emitJumpIfFalse(cond, afterThen.get());
    1399     }
    1400 
    1401     generator.emitNode(dst, m_ifBlock);
    1402     generator.emitLabel(afterThen.get());
    1403 
    1404     // FIXME: This should return the last statement executed so that it can be returned as a Completion.
    1405     return 0;
    1406 }
    1407 
    1408 // ------------------------------ IfElseNode ---------------------------------------
    1409 
    1410 RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1411 {
    1412     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1413    
    1414     RefPtr<Label> beforeElse = generator.newLabel();
    1415     RefPtr<Label> afterElse = generator.newLabel();
    1416 
    1417     if (m_condition->hasConditionContextCodegen()) {
    1418         RefPtr<Label> beforeThen = generator.newLabel();
    1419         generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), true);
    1420         generator.emitLabel(beforeThen.get());
    1421     } else {
    1422         RegisterID* cond = generator.emitNode(m_condition);
    1423         generator.emitJumpIfFalse(cond, beforeElse.get());
    1424     }
    1425 
    1426     generator.emitNode(dst, m_ifBlock);
    1427     generator.emitJump(afterElse.get());
    1428 
    1429     generator.emitLabel(beforeElse.get());
    1430 
    1431     generator.emitNode(dst, m_elseBlock);
    1432 
    1433     generator.emitLabel(afterElse.get());
    1434 
    1435     // FIXME: This should return the last statement executed so that it can be returned as a Completion.
    1436     return 0;
    1437 }
    1438 
    1439 // ------------------------------ DoWhileNode ----------------------------------
    1440 
    1441 RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1442 {
    1443     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
    1444 
    1445     RefPtr<Label> topOfLoop = generator.newLabel();
    1446     generator.emitLabel(topOfLoop.get());
    1447 
    1448     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1449    
    1450     RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
    1451 
    1452     generator.emitLabel(scope->continueTarget());
    1453     generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
    1454     if (m_expr->hasConditionContextCodegen())
    1455         generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
    1456     else {
    1457         RegisterID* cond = generator.emitNode(m_expr);
    1458         generator.emitJumpIfTrue(cond, topOfLoop.get());
    1459     }
    1460 
    1461     generator.emitLabel(scope->breakTarget());
    1462     return result.get();
    1463 }
    1464 
    1465 // ------------------------------ WhileNode ------------------------------------
    1466 
    1467 RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1468 {
    1469     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
    1470 
    1471     generator.emitJump(scope->continueTarget());
    1472 
    1473     RefPtr<Label> topOfLoop = generator.newLabel();
    1474     generator.emitLabel(topOfLoop.get());
    1475    
    1476     generator.emitNode(dst, m_statement);
    1477 
    1478     generator.emitLabel(scope->continueTarget());
    1479     generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
    1480 
    1481     if (m_expr->hasConditionContextCodegen())
    1482         generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
    1483     else {
    1484         RegisterID* cond = generator.emitNode(m_expr);
    1485         generator.emitJumpIfTrue(cond, topOfLoop.get());
    1486     }
    1487 
    1488     generator.emitLabel(scope->breakTarget());
    1489    
    1490     // FIXME: This should return the last statement executed so that it can be returned as a Completion
    1491     return 0;
    1492 }
    1493 
    1494 // ------------------------------ ForNode --------------------------------------
    1495 
    1496 RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1497 {
    1498     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
    1499 
    1500     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1501 
    1502     if (m_expr1)
    1503         generator.emitNode(generator.ignoredResult(), m_expr1);
    1504 
    1505     RefPtr<Label> condition = generator.newLabel();
    1506     generator.emitJump(condition.get());
    1507 
    1508     RefPtr<Label> topOfLoop = generator.newLabel();
    1509     generator.emitLabel(topOfLoop.get());
    1510 
    1511     RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
    1512 
    1513     generator.emitLabel(scope->continueTarget());
    1514     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1515     if (m_expr3)
    1516         generator.emitNode(generator.ignoredResult(), m_expr3);
    1517 
    1518     generator.emitLabel(condition.get());
    1519     if (m_expr2) {
    1520         if (m_expr2->hasConditionContextCodegen())
    1521             generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), false);
    1522         else {
    1523             RegisterID* cond = generator.emitNode(m_expr2);
    1524             generator.emitJumpIfTrue(cond, topOfLoop.get());
    1525         }
    1526     } else
    1527         generator.emitJump(topOfLoop.get());
    1528 
    1529     generator.emitLabel(scope->breakTarget());
    1530     return result.get();
    1531 }
    1532 
    1533 // ------------------------------ ForInNode ------------------------------------
    1534 
    1535 RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1536 {
    1537     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
    1538 
    1539     if (!m_lexpr->isLocation())
    1540         return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
    1541 
    1542     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1543 
    1544     if (m_init)
    1545         generator.emitNode(generator.ignoredResult(), m_init);
    1546 
    1547     RefPtr<RegisterID> base = generator.newTemporary();
    1548     generator.emitNode(base.get(), m_expr);
    1549     RefPtr<RegisterID> i = generator.newTemporary();
    1550     RefPtr<RegisterID> size = generator.newTemporary();
    1551     RefPtr<RegisterID> expectedSubscript;
    1552     RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
    1553     generator.emitJump(scope->continueTarget());
    1554 
    1555     RefPtr<Label> loopStart = generator.newLabel();
    1556     generator.emitLabel(loopStart.get());
    1557 
    1558     RegisterID* propertyName;
    1559     bool optimizedForinAccess = false;
    1560     if (m_lexpr->isResolveNode()) {
    1561         const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
    1562         propertyName = generator.registerFor(ident);
    1563         if (!propertyName) {
    1564             propertyName = generator.newTemporary();
    1565             RefPtr<RegisterID> protect = propertyName;
    1566             RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
    1567 
    1568             generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1569             generator.emitPutById(base, ident, propertyName);
    1570         } else {
    1571             expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
    1572             generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
    1573             optimizedForinAccess = true;
    1574         }
    1575     } else if (m_lexpr->isDotAccessorNode()) {
    1576         DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
    1577         const Identifier& ident = assignNode->identifier();
    1578         propertyName = generator.newTemporary();
    1579         RefPtr<RegisterID> protect = propertyName;
    1580         RegisterID* base = generator.emitNode(assignNode->base());
    1581 
    1582         generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
    1583         generator.emitPutById(base, ident, propertyName);
    1584     } else {
    1585         ASSERT(m_lexpr->isBracketAccessorNode());
    1586         BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
    1587         propertyName = generator.newTemporary();
    1588         RefPtr<RegisterID> protect = propertyName;
    1589         RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
    1590         RegisterID* subscript = generator.emitNode(assignNode->subscript());
    1591        
    1592         generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
    1593         generator.emitPutByVal(base.get(), subscript, propertyName);
    1594     }   
    1595 
    1596     generator.emitNode(dst, m_statement);
    1597 
    1598     if (optimizedForinAccess)
    1599         generator.popOptimisedForIn();
    1600 
    1601     generator.emitLabel(scope->continueTarget());
    1602     generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
    1603     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1604     generator.emitLabel(scope->breakTarget());
    1605     return dst;
    1606 }
    1607 
    1608 // ------------------------------ ContinueNode ---------------------------------
    1609 
    1610 // ECMA 12.7
    1611 RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1612 {
    1613     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1614    
    1615     LabelScope* scope = generator.continueTarget(m_ident);
    1616 
    1617     if (!scope)
    1618         return m_ident.isEmpty()
    1619             ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
    1620             : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
    1621 
    1622     generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
    1623     return dst;
    1624 }
    1625 
    1626 // ------------------------------ BreakNode ------------------------------------
    1627 
    1628 // ECMA 12.8
    1629 RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1630 {
    1631     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1632    
    1633     LabelScope* scope = generator.breakTarget(m_ident);
    1634    
    1635     if (!scope)
    1636         return m_ident.isEmpty()
    1637             ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
    1638             : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
    1639 
    1640     generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
    1641     return dst;
    1642 }
    1643 
    1644 // ------------------------------ ReturnNode -----------------------------------
    1645 
    1646 RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1647 {
    1648     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1649     if (generator.codeType() != FunctionCode)
    1650         return emitThrowError(generator, SyntaxError, "Invalid return statement.");
    1651 
    1652     if (dst == generator.ignoredResult())
    1653         dst = 0;
    1654     RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
    1655     RefPtr<RegisterID> returnRegister;
    1656     if (generator.scopeDepth()) {
    1657         RefPtr<Label> l0 = generator.newLabel();
    1658         if (generator.hasFinaliser() && !r0->isTemporary()) {
    1659             returnRegister = generator.emitMove(generator.newTemporary(), r0);
    1660             r0 = returnRegister.get();
    1661         }
    1662         generator.emitJumpScopes(l0.get(), 0);
    1663         generator.emitLabel(l0.get());
    1664     }
    1665     generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
    1666     return generator.emitReturn(r0);
    1667 }
    1668 
    1669 // ------------------------------ WithNode -------------------------------------
    1670 
    1671 RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1672 {
    1673     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1674    
    1675     RefPtr<RegisterID> scope = generator.newTemporary();
    1676     generator.emitNode(scope.get(), m_expr); // scope must be protected until popped
    1677     generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
    1678     generator.emitPushScope(scope.get());
    1679     RegisterID* result = generator.emitNode(dst, m_statement);
    1680     generator.emitPopScope();
    1681     return result;
    1682 }
    1683 
    1684 // ------------------------------ CaseClauseNode --------------------------------
    1685 
    1686 inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1687 {
    1688     if (m_statements)
    1689         m_statements->emitBytecode(generator, dst);
    1690 }
    1691 
    1692 // ------------------------------ CaseBlockNode --------------------------------
    1693 
    1694 enum SwitchKind {
    1695     SwitchUnset = 0,
    1696     SwitchNumber = 1,
    1697     SwitchString = 2,
    1698     SwitchNeither = 3
    1699 };
    1700 
    1701 static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
    1702 {
    1703     for (; list; list = list->getNext()) {
    1704         ExpressionNode* clauseExpression = list->getClause()->expr();
    1705         literalVector.append(clauseExpression);
    1706         if (clauseExpression->isNumber()) {
    1707             double value = static_cast<NumberNode*>(clauseExpression)->value();
    1708             int32_t intVal = static_cast<int32_t>(value);
    1709             if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
    1710                 typeForTable = SwitchNeither;
    1711                 break;
    1712             }
    1713             if (intVal < min_num)
    1714                 min_num = intVal;
    1715             if (intVal > max_num)
    1716                 max_num = intVal;
    1717             typeForTable = SwitchNumber;
    1718             continue;
    1719         }
    1720         if (clauseExpression->isString()) {
    1721             if (typeForTable & ~SwitchString) {
    1722                 typeForTable = SwitchNeither;
    1723                 break;
    1724             }
    1725             const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
    1726             if (singleCharacterSwitch &= value.size() == 1) {
    1727                 int32_t intVal = value.rep()->data()[0];
    1728                 if (intVal < min_num)
    1729                     min_num = intVal;
    1730                 if (intVal > max_num)
    1731                     max_num = intVal;
    1732             }
    1733             typeForTable = SwitchString;
    1734             continue;
    1735         }
    1736         typeForTable = SwitchNeither;
    1737         break;       
    1738     }
    1739 }
    1740    
    1741 SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
    1742 {
    1743     SwitchKind typeForTable = SwitchUnset;
    1744     bool singleCharacterSwitch = true;
    1745    
    1746     processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
    1747     processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
    1748    
    1749     if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
    1750         return SwitchInfo::SwitchNone;
    1751    
    1752     if (typeForTable == SwitchNumber) {
    1753         int32_t range = max_num - min_num;
    1754         if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
    1755             return SwitchInfo::SwitchImmediate;
    1756         return SwitchInfo::SwitchNone;
    1757     }
    1758    
    1759     ASSERT(typeForTable == SwitchString);
    1760    
    1761     if (singleCharacterSwitch) {
    1762         int32_t range = max_num - min_num;
    1763         if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
    1764             return SwitchInfo::SwitchCharacter;
    1765     }
    1766 
    1767     return SwitchInfo::SwitchString;
    1768 }
    1769 
    1770 RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
    1771 {
    1772     RefPtr<Label> defaultLabel;
    1773     Vector<RefPtr<Label>, 8> labelVector;
    1774     Vector<ExpressionNode*, 8> literalVector;
    1775     int32_t min_num = std::numeric_limits<int32_t>::max();
    1776     int32_t max_num = std::numeric_limits<int32_t>::min();
    1777     SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
    1778 
    1779     if (switchType != SwitchInfo::SwitchNone) {
    1780         // Prepare the various labels
    1781         for (uint32_t i = 0; i < literalVector.size(); i++)
    1782             labelVector.append(generator.newLabel());
    1783         defaultLabel = generator.newLabel();
    1784         generator.beginSwitch(switchExpression, switchType);
    1785     } else {
    1786         // Setup jumps
    1787         for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
    1788             RefPtr<RegisterID> clauseVal = generator.newTemporary();
    1789             generator.emitNode(clauseVal.get(), list->getClause()->expr());
    1790             generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
    1791             labelVector.append(generator.newLabel());
    1792             generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
    1793         }
    1794        
    1795         for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
    1796             RefPtr<RegisterID> clauseVal = generator.newTemporary();
    1797             generator.emitNode(clauseVal.get(), list->getClause()->expr());
    1798             generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
    1799             labelVector.append(generator.newLabel());
    1800             generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
    1801         }
    1802         defaultLabel = generator.newLabel();
    1803         generator.emitJump(defaultLabel.get());
    1804     }
    1805 
    1806     RegisterID* result = 0;
    1807 
    1808     size_t i = 0;
    1809     for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
    1810         generator.emitLabel(labelVector[i++].get());
    1811         list->getClause()->emitBytecode(generator, dst);
    1812     }
    1813 
    1814     if (m_defaultClause) {
    1815         generator.emitLabel(defaultLabel.get());
    1816         m_defaultClause->emitBytecode(generator, dst);
    1817     }
    1818 
    1819     for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
    1820         generator.emitLabel(labelVector[i++].get());
    1821         list->getClause()->emitBytecode(generator, dst);
    1822     }
    1823     if (!m_defaultClause)
    1824         generator.emitLabel(defaultLabel.get());
    1825 
    1826     ASSERT(i == labelVector.size());
    1827     if (switchType != SwitchInfo::SwitchNone) {
    1828         ASSERT(labelVector.size() == literalVector.size());
    1829         generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
    1830     }
    1831     return result;
    1832 }
    1833 
    1834 // ------------------------------ SwitchNode -----------------------------------
    1835 
    1836 RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1837 {
    1838     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1839    
    1840     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
    1841 
    1842     RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
    1843     RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
    1844 
    1845     generator.emitLabel(scope->breakTarget());
    1846     return r1;
    1847 }
    1848 
    1849 // ------------------------------ LabelNode ------------------------------------
    1850 
    1851 RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1852 {
    1853     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1854 
    1855     if (generator.breakTarget(m_name))
    1856         return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
    1857 
    1858     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
    1859     RegisterID* r0 = generator.emitNode(dst, m_statement);
    1860 
    1861     generator.emitLabel(scope->breakTarget());
    1862     return r0;
    1863 }
    1864 
    1865 // ------------------------------ ThrowNode ------------------------------------
    1866 
    1867 RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1868 {
    1869     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1870 
    1871     if (dst == generator.ignoredResult())
    1872         dst = 0;
    1873     RefPtr<RegisterID> expr = generator.emitNode(m_expr);
    1874     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    1875     generator.emitThrow(expr.get());
    1876     return 0;
    1877 }
    1878 
    1879 // ------------------------------ TryNode --------------------------------------
    1880 
    1881 RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1882 {
    1883     // NOTE: The catch and finally blocks must be labeled explicitly, so the
    1884     // optimizer knows they may be jumped to from anywhere.
    1885 
    1886     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
    1887 
    1888     RefPtr<Label> tryStartLabel = generator.newLabel();
    1889     RefPtr<Label> finallyStart;
    1890     RefPtr<RegisterID> finallyReturnAddr;
    1891     if (m_finallyBlock) {
    1892         finallyStart = generator.newLabel();
    1893         finallyReturnAddr = generator.newTemporary();
    1894         generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
    1895     }
    1896 
    1897     generator.emitLabel(tryStartLabel.get());
    1898     generator.emitNode(dst, m_tryBlock);
    1899 
    1900     if (m_catchBlock) {
    1901         RefPtr<Label> catchEndLabel = generator.newLabel();
    1902        
    1903         // Normal path: jump over the catch block.
    1904         generator.emitJump(catchEndLabel.get());
    1905 
    1906         // Uncaught exception path: the catch block.
    1907         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
    1908         RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
    1909         if (m_catchHasEval) {
    1910             RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
    1911             generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
    1912             generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
    1913             generator.emitPushScope(exceptionRegister.get());
    1914         } else
    1915             generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
    1916         generator.emitNode(dst, m_catchBlock);
    1917         generator.emitPopScope();
    1918         generator.emitLabel(catchEndLabel.get());
    1919     }
    1920 
    1921     if (m_finallyBlock) {
    1922         generator.popFinallyContext();
    1923         // there may be important registers live at the time we jump
    1924         // to a finally block (such as for a return or throw) so we
    1925         // ref the highest register ever used as a conservative
    1926         // approach to not clobbering anything important
    1927         RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
    1928         RefPtr<Label> finallyEndLabel = generator.newLabel();
    1929 
    1930         // Normal path: invoke the finally block, then jump over it.
    1931         generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
    1932         generator.emitJump(finallyEndLabel.get());
    1933 
    1934         // Uncaught exception path: invoke the finally block, then re-throw the exception.
    1935         RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
    1936         RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
    1937         generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
    1938         generator.emitThrow(tempExceptionRegister.get());
    1939 
    1940         // The finally block.
    1941         generator.emitLabel(finallyStart.get());
    1942         generator.emitNode(dst, m_finallyBlock);
    1943         generator.emitSubroutineReturn(finallyReturnAddr.get());
    1944 
    1945         generator.emitLabel(finallyEndLabel.get());
    1946     }
    1947 
    1948     return dst;
    194974}
    195075
     
    1980105}
    1981106
    1982 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
    1983 {
    1984     if (m_data->m_statements)
    1985         m_data->m_statements->emitBytecode(generator, dst);
    1986 }
    1987 
    1988107StatementNode* ScopeNode::singleStatement() const
    1989108{
     
    2009128}
    2010129
    2011 RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    2012 {
    2013     generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
    2014 
    2015     RefPtr<RegisterID> dstRegister = generator.newTemporary();
    2016     generator.emitLoad(dstRegister.get(), jsUndefined());
    2017     emitStatementsBytecode(generator, dstRegister.get());
    2018 
    2019     generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
    2020     generator.emitEnd(dstRegister.get());
    2021     return 0;
    2022 }
    2023 
    2024130// ------------------------------ EvalNode -----------------------------
    2025131
     
    2038144
    2039145    return node.release();
    2040 }
    2041 
    2042 RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    2043 {
    2044     generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
    2045 
    2046     RefPtr<RegisterID> dstRegister = generator.newTemporary();
    2047     generator.emitLoad(dstRegister.get(), jsUndefined());
    2048     emitStatementsBytecode(generator, dstRegister.get());
    2049 
    2050     generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
    2051     generator.emitEnd(dstRegister.get());
    2052     return 0;
    2053146}
    2054147
     
    2100193}
    2101194
    2102 RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    2103 {
    2104     generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
    2105     emitStatementsBytecode(generator, generator.ignoredResult());
    2106     StatementNode* singleStatement = this->singleStatement();
    2107     if (singleStatement && singleStatement->isBlock()) {
    2108         StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
    2109         if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
    2110             return 0;
    2111     }
    2112 
    2113     RegisterID* r0 = generator.emitLoad(0, jsUndefined());
    2114     generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
    2115     generator.emitReturn(r0);
    2116     return 0;
    2117 }
    2118 
    2119 // ------------------------------ FuncDeclNode ---------------------------------
    2120 
    2121 RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    2122 {
    2123     if (dst == generator.ignoredResult())
    2124         dst = 0;
    2125     return dst;
    2126 }
    2127 
    2128 // ------------------------------ FuncExprNode ---------------------------------
    2129 
    2130 RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    2131 {
    2132     return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
    2133 }
    2134 
    2135195} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.