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