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

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

REGRESSION: Hang/crash in BytecodeGenerator::constRegisterFor loading simple page
https://bugs.webkit.org/show_bug.cgi?id=28169

Reviewed by Geoff Garen.

Handle the case where someone has attempted to shadow a property
on the global object with a constant.

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