source: webkit/trunk/JavaScriptCore/parser/Nodes.cpp@ 43559

Last change on this file since 43559 was 43559, checked in by [email protected], 16 years ago

Improve function call forwarding performance

Reviewed by Gavin Barraclough

Make creation of the Arguments object occur lazily, so it
is not necessarily created for every function that references
it. Then add logic to Function.apply to allow it to avoid
allocating the Arguments object at all. Helps a lot with
the function forwarding/binding logic in jQuery, Prototype,
and numerous other JS libraries.

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