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

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

<rdar://problem/6940519> REGRESSION (Safari 4 Public Beta - TOT): google.com/adplanner shows blank page instead of site details in "basic research'

Reviewed by Darin Adler.

The problem was caused by the page returned with a function using a
var declaration list containing around ~3000 variables. The solution
to this is to flatten the comma expression representation and make
codegen comma expressions and initializer lists iterative rather than
recursive.

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