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