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

Last change on this file since 43661 was 43661, checked in by Darin Adler, 16 years ago

JavaScriptCore:

2009-05-13 Darin Adler <Darin Adler>

Revert the parser arena change. It was a slowdown, not a speedup.
Better luck next time (I'll break it up into pieces).

WebCore:

2009-05-13 Darin Adler <Darin Adler>

Revert the parser arena change. It was a slowdown, not a speedup.
Better luck next time (I'll break it up into pieces).

WebKit/mac:

2009-05-13 Darin Adler <Darin Adler>

Revert the parser arena change. It was a slowdown, not a speedup.
Better luck next time (I'll break it up into pieces).

  • Property svn:eol-style set to native
File size: 90.0 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 if (SamplingTool* sampler = globalData->interpreter->sampler())
1836 sampler->notifyOfScope(this);
1837#endif
1838}
1839
1840ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
1841 : StatementNode(globalData)
1842 , ParserArenaRefCounted(globalData)
1843 , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants))
1844 , m_features(features)
1845 , m_source(source)
1846{
1847#if ENABLE(CODEBLOCK_SAMPLING)
1848 if (SamplingTool* sampler = globalData->interpreter->sampler())
1849 sampler->notifyOfScope(this);
1850#endif
1851}
1852
1853// ------------------------------ ProgramNode -----------------------------
1854
1855inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1856 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
1857{
1858}
1859
1860PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1861{
1862 RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
1863
1864 ASSERT(node->data()->m_arena.last() == node);
1865 node->data()->m_arena.removeLast();
1866 ASSERT(!node->data()->m_arena.contains(node.get()));
1867
1868 return node.release();
1869}
1870
1871RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1872{
1873 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1874
1875 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1876 generator.emitLoad(dstRegister.get(), jsUndefined());
1877 statementListEmitCode(children(), generator, dstRegister.get());
1878
1879 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1880 generator.emitEnd(dstRegister.get());
1881 return 0;
1882}
1883
1884void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode)
1885{
1886 ScopeChain scopeChain(scopeChainNode);
1887 JSGlobalObject* globalObject = scopeChain.globalObject();
1888
1889 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
1890
1891 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get());
1892 generator.generate();
1893
1894 destroyData();
1895}
1896
1897// ------------------------------ EvalNode -----------------------------
1898
1899inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1900 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
1901{
1902}
1903
1904PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1905{
1906 RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
1907
1908 ASSERT(node->data()->m_arena.last() == node);
1909 node->data()->m_arena.removeLast();
1910 ASSERT(!node->data()->m_arena.contains(node.get()));
1911
1912 return node.release();
1913}
1914
1915RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1916{
1917 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1918
1919 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1920 generator.emitLoad(dstRegister.get(), jsUndefined());
1921 statementListEmitCode(children(), generator, dstRegister.get());
1922
1923 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1924 generator.emitEnd(dstRegister.get());
1925 return 0;
1926}
1927
1928void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode)
1929{
1930 ScopeChain scopeChain(scopeChainNode);
1931 JSGlobalObject* globalObject = scopeChain.globalObject();
1932
1933 m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
1934
1935 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
1936 generator.generate();
1937
1938 // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
1939 // so the entire ScopeNodeData cannot be destoyed.
1940 children().clear();
1941}
1942
1943EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
1944{
1945 ASSERT(!m_code);
1946
1947 ScopeChain scopeChain(scopeChainNode);
1948 JSGlobalObject* globalObject = scopeChain.globalObject();
1949
1950 m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
1951
1952 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
1953 generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
1954 generator.generate();
1955
1956 return *m_code;
1957}
1958
1959void EvalNode::mark()
1960{
1961 // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that
1962 data()->mark();
1963}
1964
1965// ------------------------------ FunctionBodyNode -----------------------------
1966
1967inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
1968 : ScopeNode(globalData)
1969#if ENABLE(JIT)
1970 , m_jitCode(0)
1971#endif
1972 , m_parameters(0)
1973 , m_parameterCount(0)
1974{
1975}
1976
1977inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
1978 : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
1979#if ENABLE(JIT)
1980 , m_jitCode(0)
1981#endif
1982 , m_parameters(0)
1983 , m_parameterCount(0)
1984{
1985}
1986
1987FunctionBodyNode::~FunctionBodyNode()
1988{
1989 for (size_t i = 0; i < m_parameterCount; ++i)
1990 m_parameters[i].~Identifier();
1991 fastFree(m_parameters);
1992}
1993
1994void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
1995{
1996 Vector<Identifier> parameters;
1997 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
1998 parameters.append(parameter->ident());
1999 size_t count = parameters.size();
2000
2001 setSource(source);
2002 finishParsing(parameters.releaseBuffer(), count);
2003}
2004
2005void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
2006{
2007 ASSERT(!source().isNull());
2008 m_parameters = parameters;
2009 m_parameterCount = parameterCount;
2010}
2011
2012void FunctionBodyNode::mark()
2013{
2014 if (m_code)
2015 m_code->mark();
2016}
2017
2018#if ENABLE(JIT)
2019PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* globalData)
2020{
2021 RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData);
2022 globalData->parser->arena().reset();
2023 body->m_jitCode = globalData->jitStubs.ctiNativeCallThunk();
2024 return body.release();
2025}
2026#endif
2027
2028FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
2029{
2030 return new FunctionBodyNode(globalData);
2031}
2032
2033PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2034{
2035 RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
2036
2037 ASSERT(node->data()->m_arena.last() == node);
2038 node->data()->m_arena.removeLast();
2039 ASSERT(!node->data()->m_arena.contains(node.get()));
2040
2041 return node.release();
2042}
2043
2044void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
2045{
2046 // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
2047 // calling Parser::parse<FunctionBodyNode>().
2048 if (!data())
2049 scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this);
2050 ASSERT(data());
2051
2052 ScopeChain scopeChain(scopeChainNode);
2053 JSGlobalObject* globalObject = scopeChain.globalObject();
2054
2055 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
2056
2057 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
2058 generator.generate();
2059
2060 destroyData();
2061}
2062
2063#if ENABLE(JIT)
2064void FunctionBodyNode::generateJITCode(ScopeChainNode* scopeChainNode)
2065{
2066 bytecode(scopeChainNode);
2067 ASSERT(m_code);
2068 ASSERT(!m_code->jitCode());
2069 JIT::compile(scopeChainNode->globalData, m_code.get());
2070 ASSERT(m_code->jitCode());
2071 m_jitCode = m_code->jitCode();
2072}
2073#endif
2074
2075CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
2076{
2077 ASSERT(!m_code);
2078
2079 ScopeChain scopeChain(scopeChainNode);
2080 JSGlobalObject* globalObject = scopeChain.globalObject();
2081
2082 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
2083
2084 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
2085 generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
2086 generator.generate();
2087
2088 return *m_code;
2089}
2090
2091RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2092{
2093 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2094 statementListEmitCode(children(), generator, generator.ignoredResult());
2095 if (children().size() && children().last()->isBlock()) {
2096 BlockNode* blockNode = static_cast<BlockNode*>(children().last());
2097 if (blockNode->children().size() && blockNode->children().last()->isReturnNode())
2098 return 0;
2099 }
2100
2101 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
2102 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2103 generator.emitReturn(r0);
2104 return 0;
2105}
2106
2107UString FunctionBodyNode::paramString() const
2108{
2109 UString s("");
2110 for (size_t pos = 0; pos < m_parameterCount; ++pos) {
2111 if (!s.isEmpty())
2112 s += ", ";
2113 s += parameters()[pos].ustring();
2114 }
2115
2116 return s;
2117}
2118
2119Identifier* FunctionBodyNode::copyParameters()
2120{
2121 Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
2122 VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
2123 return parameters;
2124}
2125
2126// ------------------------------ FuncDeclNode ---------------------------------
2127
2128JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2129{
2130 return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2131}
2132
2133RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2134{
2135 if (dst == generator.ignoredResult())
2136 dst = 0;
2137 return dst;
2138}
2139
2140// ------------------------------ FuncExprNode ---------------------------------
2141
2142RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2143{
2144 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2145}
2146
2147JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2148{
2149 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2150
2151 /*
2152 The Identifier in a FunctionExpression can be referenced from inside
2153 the FunctionExpression's FunctionBody to allow the function to call
2154 itself recursively. However, unlike in a FunctionDeclaration, the
2155 Identifier in a FunctionExpression cannot be referenced from and
2156 does not affect the scope enclosing the FunctionExpression.
2157 */
2158
2159 if (!m_ident.isNull()) {
2160 JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
2161 func->scope().push(functionScopeObject);
2162 }
2163
2164 return func;
2165}
2166
2167} // namespace JSC
Note: See TracBrowser for help on using the repository browser.