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

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

REGRESSION: fast/js/postfix-syntax.html fails with interpreter
https://bugs.webkit.org/show_bug.cgi?id=27294

Reviewed by Simon Hausmann.

When postfix operators operating on locals assign to the same local
the order of operations has to be to store the incremented value, then
store the unmodified number. Rather than implementing this subtle
semantic in the interpreter I've just made the logic explicit in the
bytecode generator, so x=x++ effectively becomes x=ToNumber(x) (for a
local var x).

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