]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecompiler/NodesCodegen.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / bytecompiler / NodesCodegen.cpp
CommitLineData
f9bf01c6
A
1/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
6fe7ccc8 4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
f9bf01c6
A
5* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
8*
9* This library is free software; you can redistribute it and/or
10* modify it under the terms of the GNU Library General Public
11* License as published by the Free Software Foundation; either
12* version 2 of the License, or (at your option) any later version.
13*
14* This library is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17* Library General Public License for more details.
18*
19* You should have received a copy of the GNU Library General Public License
20* along with this library; see the file COPYING.LIB. If not, write to
21* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22* Boston, MA 02110-1301, USA.
23*
24*/
25
26#include "config.h"
27#include "Nodes.h"
28#include "NodeConstructors.h"
29
30#include "BytecodeGenerator.h"
31#include "CallFrame.h"
32#include "Debugger.h"
33#include "JIT.h"
34#include "JSFunction.h"
35#include "JSGlobalObject.h"
36#include "JSStaticScopeObject.h"
37#include "LabelScope.h"
38#include "Lexer.h"
39#include "Operations.h"
40#include "Parser.h"
41#include "PropertyNameArray.h"
4e4e5a6f 42#include "RegExpCache.h"
f9bf01c6
A
43#include "RegExpObject.h"
44#include "SamplingTool.h"
14957cd0 45#include "UStringConcatenate.h"
f9bf01c6
A
46#include <wtf/Assertions.h>
47#include <wtf/RefCountedLeakCounter.h>
48#include <wtf/Threading.h>
49
50using namespace WTF;
51
52namespace JSC {
53
54/*
55 Details of the emitBytecode function.
56
57 Return value: The register holding the production's value.
58 dst: An optional parameter specifying the most efficient destination at
59 which to store the production's value. The callee must honor dst.
60
61 The dst argument provides for a crude form of copy propagation. For example,
62
63 x = 1
64
65 becomes
66
67 load r[x], 1
68
69 instead of
70
71 load r0, 1
72 mov r[x], r0
73
74 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
75*/
76
77// ------------------------------ ThrowableExpressionData --------------------------------
78
14957cd0 79RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const UString& message)
f9bf01c6 80{
f9bf01c6 81 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
14957cd0
A
82 generator.emitThrowReferenceError(message);
83 return generator.newTemporary();
f9bf01c6
A
84}
85
86// ------------------------------ NullNode -------------------------------------
87
88RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
89{
90 if (dst == generator.ignoredResult())
91 return 0;
92 return generator.emitLoad(dst, jsNull());
93}
94
95// ------------------------------ BooleanNode ----------------------------------
96
97RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
98{
99 if (dst == generator.ignoredResult())
100 return 0;
101 return generator.emitLoad(dst, m_value);
102}
103
104// ------------------------------ NumberNode -----------------------------------
105
106RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
107{
108 if (dst == generator.ignoredResult())
109 return 0;
110 return generator.emitLoad(dst, m_value);
111}
112
113// ------------------------------ StringNode -----------------------------------
114
115RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
116{
117 if (dst == generator.ignoredResult())
118 return 0;
119 return generator.emitLoad(dst, m_value);
120}
121
122// ------------------------------ RegExpNode -----------------------------------
123
124RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
125{
f9bf01c6
A
126 if (dst == generator.ignoredResult())
127 return 0;
6fe7ccc8 128 return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.globalData(), m_pattern.ustring(), regExpFlags(m_flags.ustring())));
f9bf01c6
A
129}
130
131// ------------------------------ ThisNode -------------------------------------
132
133RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
134{
135 if (dst == generator.ignoredResult())
136 return 0;
137 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
138}
139
140// ------------------------------ ResolveNode ----------------------------------
141
142bool ResolveNode::isPure(BytecodeGenerator& generator) const
143{
144 return generator.isLocal(m_ident);
145}
146
147RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
148{
149 if (RegisterID* local = generator.registerFor(m_ident)) {
150 if (dst == generator.ignoredResult())
151 return 0;
152 return generator.moveToDestinationIfNeeded(dst, local);
153 }
154
14957cd0 155 generator.emitExpressionInfo(m_startOffset + m_ident.length(), m_ident.length(), 0);
f9bf01c6
A
156 return generator.emitResolve(generator.finalDestination(dst), m_ident);
157}
158
159// ------------------------------ ArrayNode ------------------------------------
160
161RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
162{
163 // FIXME: Should we put all of this code into emitNewArray?
164
165 unsigned length = 0;
166 ElementNode* firstPutElement;
167 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
168 if (firstPutElement->elision())
169 break;
170 ++length;
171 }
172
173 if (!firstPutElement && !m_elision)
14957cd0 174 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
f9bf01c6 175
14957cd0 176 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
f9bf01c6
A
177
178 for (ElementNode* n = firstPutElement; n; n = n->next()) {
179 RegisterID* value = generator.emitNode(n->value());
180 length += n->elision();
181 generator.emitPutByIndex(array.get(), length++, value);
182 }
183
184 if (m_elision) {
14957cd0 185 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
f9bf01c6
A
186 generator.emitPutById(array.get(), generator.propertyNames().length, value);
187 }
188
189 return generator.moveToDestinationIfNeeded(dst, array.get());
190}
191
192bool ArrayNode::isSimpleArray() const
193{
194 if (m_elision || m_optional)
195 return false;
196 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
197 if (ptr->elision())
198 return false;
199 }
200 return true;
201}
202
6fe7ccc8 203ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData, int lineNumber) const
f9bf01c6
A
204{
205 ASSERT(!m_elision && !m_optional);
206 ElementNode* ptr = m_element;
207 if (!ptr)
208 return 0;
6fe7ccc8 209 ArgumentListNode* head = new (globalData) ArgumentListNode(lineNumber, ptr->value());
f9bf01c6
A
210 ArgumentListNode* tail = head;
211 ptr = ptr->next();
212 for (; ptr; ptr = ptr->next()) {
213 ASSERT(!ptr->elision());
6fe7ccc8 214 tail = new (globalData) ArgumentListNode(lineNumber, tail, ptr->value());
f9bf01c6
A
215 }
216 return head;
217}
218
219// ------------------------------ ObjectLiteralNode ----------------------------
220
221RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
222{
223 if (!m_list) {
224 if (dst == generator.ignoredResult())
225 return 0;
226 return generator.emitNewObject(generator.finalDestination(dst));
227 }
228 return generator.emitNode(dst, m_list);
229}
230
231// ------------------------------ PropertyListNode -----------------------------
232
233RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
234{
235 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
236
237 generator.emitNewObject(newObj.get());
238
6fe7ccc8
A
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;
f9bf01c6 271 }
6fe7ccc8
A
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 }
f9bf01c6 306 }
6fe7ccc8
A
307
308 generator.emitPutGetterSetter(newObj.get(), node->name(), getterReg.get(), setterReg.get());
f9bf01c6
A
309 }
310 }
6fe7ccc8 311
f9bf01c6
A
312 return generator.moveToDestinationIfNeeded(dst, newObj.get());
313}
314
315// ------------------------------ BracketAccessorNode --------------------------------
316
317RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
318{
14957cd0
A
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
f9bf01c6
A
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
333RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
334{
14957cd0
A
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
345nonArgumentsPath:
f9bf01c6
A
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
353RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
354{
355 ASSERT(m_expr);
356 return generator.emitNode(dst, m_expr);
357}
358
359// ------------------------------ NewExprNode ----------------------------------
360
361RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
362{
363 RefPtr<RegisterID> func = generator.emitNode(m_expr);
14957cd0
A
364 CallArguments callArguments(generator, m_args);
365 return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset());
366}
367
6fe7ccc8 368inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
14957cd0
A
369 : m_argumentsNode(argumentsNode)
370{
371 if (generator.shouldEmitProfileHooks())
372 m_profileHookRegister = generator.newTemporary();
6fe7ccc8
A
373
374 size_t argumentCountIncludingThis = 1; // 'this' register.
14957cd0 375 if (argumentsNode) {
6fe7ccc8
A
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);
14957cd0 384 }
f9bf01c6
A
385}
386
6fe7ccc8
A
387inline 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
f9bf01c6
A
394// ------------------------------ EvalFunctionCallNode ----------------------------------
395
396RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
397{
398 RefPtr<RegisterID> func = generator.tempDestination(dst);
14957cd0 399 CallArguments callArguments(generator, m_args);
f9bf01c6 400 generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
6fe7ccc8 401 generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
14957cd0 402 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
f9bf01c6
A
403}
404
405// ------------------------------ FunctionCallValueNode ----------------------------------
406
407RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
408{
409 RefPtr<RegisterID> func = generator.emitNode(m_expr);
14957cd0
A
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());
f9bf01c6
A
413}
414
415// ------------------------------ FunctionCallResolveNode ----------------------------------
416
417RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
418{
419 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
6fe7ccc8 420 RefPtr<RegisterID> function = generator.emitMove(generator.tempDestination(dst), local.get());
14957cd0
A
421 CallArguments callArguments(generator, m_args);
422 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
6fe7ccc8 423 return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), function.get(), callArguments, divot(), startOffset(), endOffset());
f9bf01c6
A
424 }
425
426 int index = 0;
427 size_t depth = 0;
428 JSObject* globalObject = 0;
4e4e5a6f
A
429 bool requiresDynamicChecks = false;
430 if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
f9bf01c6 431 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
14957cd0
A
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());
f9bf01c6
A
435 }
436
437 RefPtr<RegisterID> func = generator.newTemporary();
14957cd0 438 CallArguments callArguments(generator, m_args);
f9bf01c6 439 int identifierStart = divot() - startOffset();
14957cd0 440 generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
6fe7ccc8 441 generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), m_ident);
14957cd0 442 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
f9bf01c6
A
443}
444
445// ------------------------------ FunctionCallBracketNode ----------------------------------
446
447RegisterID* 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);
14957cd0
A
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());
f9bf01c6
A
456}
457
458// ------------------------------ FunctionCallDotNode ----------------------------------
459
460RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
461{
462 RefPtr<RegisterID> function = generator.tempDestination(dst);
14957cd0
A
463 CallArguments callArguments(generator, m_args);
464 generator.emitNode(callArguments.thisRegister(), m_base);
f9bf01c6
A
465 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
466 generator.emitMethodCheck();
14957cd0
A
467 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
468 return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset());
f9bf01c6
A
469}
470
471RegisterID* 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);
14957cd0 478 RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
f9bf01c6
A
479 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
480 {
f9bf01c6 481 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
14957cd0 482 ArgumentListNode* oldList = m_args->m_listNode;
f9bf01c6 483 m_args->m_listNode = m_args->m_listNode->m_next;
f9bf01c6 484
14957cd0
A
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;
14957cd0
A
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 }
f9bf01c6
A
499 }
500 generator.emitLabel(realCall.get());
501 {
14957cd0
A
502 CallArguments callArguments(generator, m_args);
503 generator.emitMove(callArguments.thisRegister(), base.get());
504 generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
f9bf01c6
A
505 }
506 generator.emitLabel(end.get());
14957cd0 507 return finalDestinationOrIgnored.get();
f9bf01c6 508}
14957cd0 509
f9bf01c6
A
510static 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
516RegisterID* 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);
14957cd0 528 RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
f9bf01c6
A
529 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
530 {
531 if (mayBeCall) {
f9bf01c6 532 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
14957cd0
A
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);
6fe7ccc8 537 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData(), 0);
14957cd0
A
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());
f9bf01c6 548 }
14957cd0
A
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 }
f9bf01c6
A
556 } else {
557 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
6fe7ccc8
A
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;
f9bf01c6 564 ArgumentListNode* args = m_args->m_listNode->m_next;
6fe7ccc8
A
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.
f9bf01c6
A
572 while ((args = args->m_next))
573 generator.emitNode(args->m_expr);
574
6fe7ccc8 575 generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), startOffset(), endOffset());
f9bf01c6
A
576 }
577 generator.emitJump(end.get());
578 }
579 generator.emitLabel(realCall.get());
580 {
14957cd0
A
581 CallArguments callArguments(generator, m_args);
582 generator.emitMove(callArguments.thisRegister(), base.get());
583 generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
f9bf01c6
A
584 }
585 generator.emitLabel(end.get());
14957cd0 586 return finalDestinationOrIgnored.get();
f9bf01c6
A
587}
588
589// ------------------------------ PostfixResolveNode ----------------------------------
590
591static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
592{
593 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
594}
595
596static 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
603RegisterID* 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;
4e4e5a6f
A
620 bool requiresDynamicChecks = false;
621 if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
f9bf01c6
A
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
650RegisterID* 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
674RegisterID* 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
697RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
698{
14957cd0 699 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
f9bf01c6
A
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
706RegisterID* 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
718RegisterID* 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
729RegisterID* 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
739RegisterID* 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
749RegisterID* 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
761RegisterID* 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
778RegisterID* 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
790RegisterID* 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;
4e4e5a6f 807 bool requiresDynamicChecks = false;
6fe7ccc8 808 if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
f9bf01c6
A
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
825RegisterID* 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
844RegisterID* 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
862RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
863{
14957cd0 864 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
f9bf01c6
A
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
871RegisterID* 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
6fe7ccc8
A
877// ------------------------------ BitwiseNotNode -----------------------------------
878
879RegisterID* 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
f9bf01c6
A
886// ------------------------------ LogicalNotNode -----------------------------------
887
888void 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//
927RegisterID* 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
1017RegisterID* 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
1037RegisterID* 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
1050RegisterID* 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
f9bf01c6
A
1057RegisterID* 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
1065RegisterID* 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());
14957cd0
A
1071 generator.emitCheckHasInstance(src2.get());
1072
1073 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
f9bf01c6
A
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
1082RegisterID* 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
1098void 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
1128RegisterID* 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?
1157static 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
1211RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1212{
1213 if (RegisterID* local = generator.registerFor(m_ident)) {
6fe7ccc8 1214 if (generator.isLocalConstant(m_ident))
f9bf01c6 1215 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
6fe7ccc8 1216
f9bf01c6
A
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;
4e4e5a6f
A
1232 bool requiresDynamicChecks = false;
1233 if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
f9bf01c6
A
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);
14957cd0 1241 generator.emitExpressionInfo(divot() - startOffset() + m_ident.length(), m_ident.length(), 0);
f9bf01c6
A
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
1249RegisterID* 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;
4e4e5a6f
A
1262 bool requiresDynamicChecks = false;
1263 if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
f9bf01c6
A
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
14957cd0 1271 RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), m_ident);
f9bf01c6
A
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
1281RegisterID* 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());
6fe7ccc8
A
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);
f9bf01c6
A
1290}
1291
1292// ------------------------------ ReadModifyDotNode -----------------------------------
1293
1294RegisterID* 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
1308RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1309{
14957cd0 1310 return emitThrowReferenceError(generator, "Left side of assignment is not a reference.");
f9bf01c6
A
1311}
1312
1313// ------------------------------ AssignBracketNode -----------------------------------
1314
1315RegisterID* 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());
6fe7ccc8
A
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);
f9bf01c6
A
1326}
1327
1328// ------------------------------ ReadModifyBracketNode -----------------------------------
1329
1330RegisterID* 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
1347RegisterID* 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
1357RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1358{
6fe7ccc8 1359 // FIXME: This code does not match the behavior of const in Firefox.
f9bf01c6
A
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
6fe7ccc8
A
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);
f9bf01c6 1382 }
6fe7ccc8
A
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.
f9bf01c6 1389 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
6fe7ccc8 1390 return generator.emitPutById(base.get(), m_ident, value.get());
f9bf01c6
A
1391}
1392
1393RegisterID* 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
1404RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1405{
1406 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1407 return generator.emitNode(m_next);
1408}
1409
1410// ------------------------------ SourceElements -------------------------------
1411
1412
1413inline StatementNode* SourceElements::lastStatement() const
1414{
1415 size_t size = m_statements.size();
1416 return size ? m_statements[size - 1] : 0;
1417}
1418
1419inline 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
1428inline StatementNode* BlockNode::lastStatement() const
1429{
1430 return m_statements ? m_statements->lastStatement() : 0;
1431}
1432
14957cd0
A
1433inline StatementNode* BlockNode::singleStatement() const
1434{
1435 return m_statements ? m_statements->singleStatement() : 0;
1436}
1437
f9bf01c6
A
1438RegisterID* 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
1447RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1448{
1449 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1450 return dst;
1451}
1452
1453// ------------------------------ DebuggerStatementNode ---------------------------
1454
1455RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1456{
1457 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1458 return dst;
1459}
1460
1461// ------------------------------ ExprStatementNode ----------------------------
1462
1463RegisterID* 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
1472RegisterID* 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
1481RegisterID* 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
1505RegisterID* 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
1536RegisterID* 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());
6fe7ccc8 1542 generator.emitLoopHint();
f9bf01c6
A
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
1562RegisterID* 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());
6fe7ccc8 1570 generator.emitLoopHint();
f9bf01c6
A
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
1592RegisterID* 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());
6fe7ccc8 1606 generator.emitLoopHint();
f9bf01c6
A
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
1632RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1633{
1634 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1635
1636 if (!m_lexpr->isLocation())
14957cd0 1637 return emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
f9bf01c6
A
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());
6fe7ccc8 1654 generator.emitLoopHint();
f9bf01c6
A
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;
14957cd0 1664 RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), ident);
f9bf01c6
A
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
1709RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1710{
1711 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1712
1713 LabelScope* scope = generator.continueTarget(m_ident);
14957cd0 1714 ASSERT(scope);
f9bf01c6
A
1715
1716 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
1717 return dst;
1718}
1719
1720// ------------------------------ BreakNode ------------------------------------
1721
1722// ECMA 12.8
1723RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1724{
1725 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1726
1727 LabelScope* scope = generator.breakTarget(m_ident);
14957cd0 1728 ASSERT(scope);
f9bf01c6
A
1729
1730 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
1731 return dst;
1732}
1733
1734// ------------------------------ ReturnNode -----------------------------------
1735
1736RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1737{
1738 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
14957cd0 1739 ASSERT(generator.codeType() == FunctionCode);
f9bf01c6
A
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();
6fe7ccc8 1747 if (generator.hasFinaliser()) {
f9bf01c6
A
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
1760RegisterID* 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
1775inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1776{
1777 if (m_statements)
1778 m_statements->emitBytecode(generator, dst);
1779}
1780
1781// ------------------------------ CaseBlockNode --------------------------------
1782
1783enum SwitchKind {
1784 SwitchUnset = 0,
1785 SwitchNumber = 1,
1786 SwitchString = 2,
1787 SwitchNeither = 3
1788};
1789
1790static 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();
14957cd0 1815 if (singleCharacterSwitch &= value.length() == 1) {
6fe7ccc8 1816 int32_t intVal = value[0];
f9bf01c6
A
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
1830SwitchInfo::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
1859RegisterID* 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
1925RegisterID* 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
1940RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1941{
1942 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1943
14957cd0 1944 ASSERT(!generator.breakTarget(m_name));
f9bf01c6
A
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
1955RegisterID* 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
1969RegisterID* 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();
6fe7ccc8
A
1977 if (m_finallyBlock)
1978 generator.pushFinallyContext(m_finallyBlock);
f9bf01c6
A
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());
6fe7ccc8 1992 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
f9bf01c6
A
1993 generator.emitNode(dst, m_catchBlock);
1994 generator.emitPopScope();
1995 generator.emitLabel(catchEndLabel.get());
1996 }
1997
1998 if (m_finallyBlock) {
1999 generator.popFinallyContext();
6fe7ccc8 2000
f9bf01c6
A
2001 RefPtr<Label> finallyEndLabel = generator.newLabel();
2002
6fe7ccc8
A
2003 // Normal path: run the finally code, and jump to the end.
2004 generator.emitNode(dst, m_finallyBlock);
f9bf01c6
A
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());
f9bf01c6 2010 generator.emitNode(dst, m_finallyBlock);
6fe7ccc8 2011 generator.emitThrow(tempExceptionRegister.get());
f9bf01c6
A
2012
2013 generator.emitLabel(finallyEndLabel.get());
2014 }
2015
2016 return dst;
2017}
2018
2019// ------------------------------ ScopeNode -----------------------------
2020
2021inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2022{
6fe7ccc8
A
2023 if (m_statements)
2024 m_statements->emitBytecode(generator, dst);
f9bf01c6
A
2025}
2026
2027// ------------------------------ ProgramNode -----------------------------
2028
2029RegisterID* 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
2044RegisterID* 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
2059RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2060{
2061 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2062 emitStatementsBytecode(generator, generator.ignoredResult());
14957cd0 2063
f9bf01c6 2064 StatementNode* singleStatement = this->singleStatement();
14957cd0
A
2065 ReturnNode* returnNode = 0;
2066
2067 // Check for a return statement at the end of a function composed of a single block.
f9bf01c6
A
2068 if (singleStatement && singleStatement->isBlock()) {
2069 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2070 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
14957cd0
A
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();
6fe7ccc8
A
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);
14957cd0
A
2094 }
2095 }
f9bf01c6
A
2096 }
2097
f9bf01c6
A
2098 return 0;
2099}
2100
2101// ------------------------------ FuncDeclNode ---------------------------------
2102
2103RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2104{
2105 if (dst == generator.ignoredResult())
2106 dst = 0;
2107 return dst;
2108}
2109
2110// ------------------------------ FuncExprNode ---------------------------------
2111
2112RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2113{
2114 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2115}
2116
2117} // namespace JSC