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

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

Stack overflow crash in JavaScript garbage collector mark pass
https://bugs.webkit.org/show_bug.cgi?id=12216

Reviewed by Gavin Barraclough and Sam Weinig

Make the GC mark phase iterative by using an explicit mark stack.
To do this marking any single object is performed in multiple stages

  • The object is appended to the MarkStack, this sets the marked bit for the object using the new markDirect() function, and then returns
  • When the MarkStack is drain()ed the object is popped off the stack and markChildren(MarkStack&) is called on the object to collect all of its children. drain() then repeats until the stack is empty.

Additionally I renamed a number of methods from 'mark' to 'markAggregate'
in order to make it more clear that marking of those object was not
going to result in an actual recursive mark.

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