source: webkit/trunk/JavaScriptCore/kjs/nodes.cpp@ 36794

Last change on this file since 36794 was 36794, checked in by Darin Adler, 17 years ago

2008-09-22 Darin Adler <Darin Adler>

Reviewed by Sam Weinig.

Speeds up v8-raytrace by 7.2%.

  • kjs/nodes.cpp: (JSC::FunctionBodyNode::FunctionBodyNode): Initialize m_refCount to 0.
  • kjs/nodes.h: (JSC::FunctionBodyNode::ref): Call base class ref once, and thereafter use m_refCount. (JSC::FunctionBodyNode::deref): Ditto, but the deref side.
  • Property svn:eol-style set to native
File size: 75.7 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 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
29#include "CodeGenerator.h"
30#include "ExecState.h"
31#include "JSGlobalObject.h"
32#include "JSStaticScopeObject.h"
33#include "Parser.h"
34#include "PropertyNameArray.h"
35#include "RegExpObject.h"
36#include "debugger.h"
37#include "lexer.h"
38#include "operations.h"
39#include "SamplingTool.h"
40#include <math.h>
41#include <wtf/Assertions.h>
42#include <wtf/HashCountedSet.h>
43#include <wtf/HashSet.h>
44#include <wtf/MathExtras.h>
45#include <wtf/RefCountedLeakCounter.h>
46#include <wtf/Threading.h>
47
48using namespace WTF;
49
50namespace JSC {
51
52// ------------------------------ Node -----------------------------------------
53
54#ifndef NDEBUG
55static RefCountedLeakCounter parserRefCountedCounter("JSC::Node");
56#endif
57
58ParserRefCounted::ParserRefCounted(JSGlobalData* globalData)
59 : m_globalData(globalData)
60{
61#ifndef NDEBUG
62 parserRefCountedCounter.increment();
63#endif
64 if (!m_globalData->newParserObjects)
65 m_globalData->newParserObjects = new HashSet<ParserRefCounted*>;
66 m_globalData->newParserObjects->add(this);
67 ASSERT(m_globalData->newParserObjects->contains(this));
68}
69
70ParserRefCounted::~ParserRefCounted()
71{
72#ifndef NDEBUG
73 parserRefCountedCounter.decrement();
74#endif
75}
76
77void ParserRefCounted::ref()
78{
79 // bumping from 0 to 1 is just removing from the new nodes set
80 if (m_globalData->newParserObjects) {
81 HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this);
82 if (it != m_globalData->newParserObjects->end()) {
83 m_globalData->newParserObjects->remove(it);
84 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
85 return;
86 }
87 }
88
89 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
90
91 if (!m_globalData->parserObjectExtraRefCounts)
92 m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
93 m_globalData->parserObjectExtraRefCounts->add(this);
94}
95
96void ParserRefCounted::deref()
97{
98 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
99
100 if (!m_globalData->parserObjectExtraRefCounts) {
101 delete this;
102 return;
103 }
104
105 HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this);
106 if (it == m_globalData->parserObjectExtraRefCounts->end())
107 delete this;
108 else
109 m_globalData->parserObjectExtraRefCounts->remove(it);
110}
111
112bool ParserRefCounted::hasOneRef()
113{
114 if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) {
115 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
116 return false;
117 }
118
119 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
120
121 if (!m_globalData->parserObjectExtraRefCounts)
122 return true;
123
124 return !m_globalData->parserObjectExtraRefCounts->contains(this);
125}
126
127void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData)
128{
129 if (!globalData->newParserObjects)
130 return;
131
132#ifndef NDEBUG
133 HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end();
134 for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it)
135 ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it));
136#endif
137 deleteAllValues(*globalData->newParserObjects);
138 delete globalData->newParserObjects;
139 globalData->newParserObjects = 0;
140}
141
142Node::Node(JSGlobalData* globalData)
143 : ParserRefCounted(globalData)
144 , m_expectedReturnType(ObjectType)
145{
146 m_line = globalData->lexer->lineNo();
147}
148
149Node::Node(JSGlobalData* globalData, JSType expectedReturn)
150 : ParserRefCounted(globalData)
151 , m_expectedReturnType(expectedReturn)
152{
153 m_line = globalData->lexer->lineNo();
154}
155
156static void substitute(UString& string, const UString& substring) JSC_FAST_CALL;
157static void substitute(UString& string, const UString& substring)
158{
159 int position = string.find("%s");
160 ASSERT(position != -1);
161 UString newString = string.substr(0, position);
162 newString.append(substring);
163 newString.append(string.substr(position + 2));
164 string = newString;
165}
166
167RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
168{
169 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
170 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalExec(), msg));
171 generator.emitThrow(exception);
172 return exception;
173}
174
175RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
176{
177 UString message = msg;
178 substitute(message, label.ustring());
179 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
180 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalExec(), message));
181 generator.emitThrow(exception);
182 return exception;
183}
184
185// ------------------------------ StatementNode --------------------------------
186
187StatementNode::StatementNode(JSGlobalData* globalData)
188 : Node(globalData)
189 , m_lastLine(-1)
190{
191}
192
193void StatementNode::setLoc(int firstLine, int lastLine)
194{
195 m_line = firstLine;
196 m_lastLine = lastLine;
197}
198
199// ------------------------------ SourceElements --------------------------------
200
201void SourceElements::append(PassRefPtr<StatementNode> statement)
202{
203 if (statement->isEmptyStatement())
204 return;
205
206 m_statements.append(statement);
207}
208
209// ------------------------------ BreakpointCheckStatement --------------------------------
210
211BreakpointCheckStatement::BreakpointCheckStatement(JSGlobalData* globalData, PassRefPtr<StatementNode> statement)
212 : StatementNode(globalData)
213 , m_statement(statement)
214{
215 ASSERT(m_statement);
216}
217
218void BreakpointCheckStatement::streamTo(SourceStream& stream) const
219{
220 m_statement->streamTo(stream);
221}
222
223// ------------------------------ NullNode -------------------------------------
224
225RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
226{
227 if (dst == ignoredResult())
228 return 0;
229 return generator.emitLoad(dst, jsNull());
230}
231
232// ------------------------------ BooleanNode ----------------------------------
233
234RegisterID* BooleanNode::emitCode(CodeGenerator& generator, RegisterID* dst)
235{
236 if (dst == ignoredResult())
237 return 0;
238 return generator.emitLoad(dst, m_value);
239}
240
241// ------------------------------ NumberNode -----------------------------------
242
243RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
244{
245 if (dst == ignoredResult())
246 return 0;
247 return generator.emitLoad(dst, m_double);
248}
249
250// ------------------------------ StringNode -----------------------------------
251
252RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
253{
254 if (dst == ignoredResult())
255 return 0;
256 return generator.emitLoad(dst, m_value);
257}
258
259// ------------------------------ RegExpNode -----------------------------------
260
261RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
262{
263 RefPtr<RegExp> regExp = RegExp::create(generator.globalExec(), m_pattern, m_flags);
264 if (!regExp->isValid())
265 return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
266 if (dst == ignoredResult())
267 return 0;
268 return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
269}
270
271// ------------------------------ ThisNode -------------------------------------
272
273RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
274{
275 if (dst == ignoredResult())
276 return 0;
277 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
278}
279
280// ------------------------------ ResolveNode ----------------------------------
281
282bool ResolveNode::isPure(CodeGenerator& generator) const
283{
284 return generator.isLocal(m_ident);
285}
286
287RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
288{
289 if (RegisterID* local = generator.registerForLocal(m_ident)) {
290 if (dst == ignoredResult())
291 return 0;
292 return generator.moveToDestinationIfNeeded(dst, local);
293 }
294
295 generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
296 return generator.emitResolve(generator.finalDestination(dst), m_ident);
297}
298
299// ------------------------------ ArrayNode ------------------------------------
300
301RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
302{
303 // FIXME: Should we put all of this code into emitNewArray?
304
305 unsigned length = 0;
306 ElementNode* firstPutElement;
307 for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) {
308 if (firstPutElement->elision())
309 break;
310 ++length;
311 }
312
313 if (!firstPutElement && !m_elision)
314 return generator.emitNewArray(generator.finalDestination(dst), m_element.get());
315
316 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get());
317
318 for (ElementNode* n = firstPutElement; n; n = n->next()) {
319 RegisterID* value = generator.emitNode(n->value());
320 length += n->elision();
321 generator.emitPutByIndex(array.get(), length++, value);
322 }
323
324 if (m_elision) {
325 RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalExec(), m_elision + length));
326 generator.emitPutById(array.get(), generator.propertyNames().length, value);
327 }
328
329 return generator.moveToDestinationIfNeeded(dst, array.get());
330}
331
332// ------------------------------ ObjectLiteralNode ----------------------------
333
334RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
335{
336 if (!m_list) {
337 if (dst == ignoredResult())
338 return 0;
339 return generator.emitNewObject(generator.finalDestination(dst));
340 }
341 return generator.emitNode(dst, m_list.get());
342}
343
344// ------------------------------ PropertyListNode -----------------------------
345
346RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
347{
348 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
349
350 generator.emitNewObject(newObj.get());
351
352 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
353 RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
354
355 switch (p->m_node->m_type) {
356 case PropertyNode::Constant: {
357 generator.emitPutById(newObj.get(), p->m_node->name(), value);
358 break;
359 }
360 case PropertyNode::Getter: {
361 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
362 break;
363 }
364 case PropertyNode::Setter: {
365 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
366 break;
367 }
368 default:
369 ASSERT_NOT_REACHED();
370 }
371 }
372
373 return generator.moveToDestinationIfNeeded(dst, newObj.get());
374}
375
376// ------------------------------ BracketAccessorNode --------------------------------
377
378RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
379{
380 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
381 RegisterID* property = generator.emitNode(m_subscript.get());
382 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
383 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
384}
385
386// ------------------------------ DotAccessorNode --------------------------------
387
388RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
389{
390 RegisterID* base = generator.emitNode(m_base.get());
391 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
392 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
393}
394
395// ------------------------------ ArgumentListNode -----------------------------
396
397RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
398{
399 ASSERT(m_expr);
400 return generator.emitNode(dst, m_expr.get());
401}
402
403// ------------------------------ NewExprNode ----------------------------------
404
405RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
406{
407 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
408 return generator.emitConstruct(generator.finalDestination(dst, r0.get()), r0.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
409}
410
411RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
412{
413 RefPtr<RegisterID> base = generator.tempDestination(dst);
414 RegisterID* func = generator.newTemporary();
415 generator.emitResolveWithBase(base.get(), func, generator.propertyNames().eval);
416 return generator.emitCallEval(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
417}
418
419RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
420{
421 RegisterID* func = generator.emitNode(m_expr.get());
422 return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
423}
424
425RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
426{
427 if (RegisterID* local = generator.registerForLocal(m_ident))
428 return generator.emitCall(generator.finalDestination(dst), local, 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
429
430 int index = 0;
431 size_t depth = 0;
432 JSValue* globalObject = 0;
433 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
434 RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
435 return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
436 }
437
438 RefPtr<RegisterID> base = generator.tempDestination(dst);
439 RegisterID* func = generator.newTemporary();
440 int identifierStart = m_divot - m_startOffset;
441 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
442 generator.emitResolveFunction(base.get(), func, m_ident);
443 return generator.emitCall(generator.finalDestination(dst, base.get()), func, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
444}
445
446RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
447{
448 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
449 RegisterID* property = generator.emitNode(m_subscript.get());
450 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
451 RegisterID* function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
452 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
453}
454
455RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
456{
457 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
458 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
459 RegisterID* function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
460 return generator.emitCall(generator.finalDestination(dst, base.get()), function, base.get(), m_args.get(), m_divot, m_startOffset, m_endOffset);
461}
462
463// ------------------------------ PostfixResolveNode ----------------------------------
464
465static RegisterID* emitPreIncOrDec(CodeGenerator& generator, RegisterID* srcDst, Operator oper)
466{
467 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
468}
469
470static RegisterID* emitPostIncOrDec(CodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
471{
472 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
473}
474
475RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
476{
477 if (RegisterID* local = generator.registerForLocal(m_ident)) {
478 if (generator.isLocalConstant(m_ident)) {
479 if (dst == ignoredResult())
480 return 0;
481 return generator.emitToJSNumber(generator.finalDestination(dst), local);
482 }
483
484 if (dst == ignoredResult())
485 return emitPreIncOrDec(generator, local, m_operator);
486 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
487 }
488
489 int index = 0;
490 size_t depth = 0;
491 JSValue* globalObject = 0;
492 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
493 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
494 RegisterID* oldValue;
495 if (dst == ignoredResult()) {
496 oldValue = 0;
497 emitPreIncOrDec(generator, value.get(), m_operator);
498 } else {
499 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
500 }
501 generator.emitPutScopedVar(depth, index, value.get(), globalObject);
502 return oldValue;
503 }
504
505 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
506 RefPtr<RegisterID> value = generator.newTemporary();
507 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
508 RegisterID* oldValue;
509 if (dst == ignoredResult()) {
510 oldValue = 0;
511 emitPreIncOrDec(generator, value.get(), m_operator);
512 } else {
513 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
514 }
515 generator.emitPutById(base.get(), m_ident, value.get());
516 return oldValue;
517}
518
519// ------------------------------ PostfixBracketNode ----------------------------------
520
521RegisterID* PostfixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
522{
523 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
524 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
525
526 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
527 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
528 RegisterID* oldValue;
529 if (dst == ignoredResult()) {
530 oldValue = 0;
531 if (m_operator == OpPlusPlus)
532 generator.emitPreInc(value.get());
533 else
534 generator.emitPreDec(value.get());
535 } else {
536 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
537 }
538 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
539 generator.emitPutByVal(base.get(), property.get(), value.get());
540 return oldValue;
541}
542
543// ------------------------------ PostfixDotNode ----------------------------------
544
545RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
546{
547 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
548
549 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
550 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
551 RegisterID* oldValue;
552 if (dst == ignoredResult()) {
553 oldValue = 0;
554 if (m_operator == OpPlusPlus)
555 generator.emitPreInc(value.get());
556 else
557 generator.emitPreDec(value.get());
558 } else {
559 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
560 }
561 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
562 generator.emitPutById(base.get(), m_ident, value.get());
563 return oldValue;
564}
565
566// ------------------------------ PostfixErrorNode -----------------------------------
567
568RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
569{
570 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.");
571}
572
573// ------------------------------ DeleteResolveNode -----------------------------------
574
575RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
576{
577 if (generator.registerForLocal(m_ident))
578 return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
579
580 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
581 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
582 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
583}
584
585// ------------------------------ DeleteBracketNode -----------------------------------
586
587RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
588{
589 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
590 RegisterID* r1 = generator.emitNode(m_subscript.get());
591
592 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
593 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
594}
595
596// ------------------------------ DeleteDotNode -----------------------------------
597
598RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
599{
600 RegisterID* r0 = generator.emitNode(m_base.get());
601
602 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
603 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
604}
605
606// ------------------------------ DeleteValueNode -----------------------------------
607
608RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
609{
610 generator.emitNode(ignoredResult(), m_expr.get());
611
612 // delete on a non-location expression ignores the value and returns true
613 return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
614}
615
616// ------------------------------ VoidNode -------------------------------------
617
618RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
619{
620 if (dst == ignoredResult()) {
621 generator.emitNode(ignoredResult(), m_expr.get());
622 return 0;
623 }
624 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
625 return generator.emitLoad(dst, jsUndefined());
626}
627
628// ------------------------------ TypeOfValueNode -----------------------------------
629
630RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
631{
632 if (RegisterID* local = generator.registerForLocal(m_ident)) {
633 if (dst == ignoredResult())
634 return 0;
635 return generator.emitTypeOf(generator.finalDestination(dst), local);
636 }
637
638 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
639 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
640 if (dst == ignoredResult())
641 return 0;
642 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
643}
644
645// ------------------------------ TypeOfValueNode -----------------------------------
646
647RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
648{
649 if (dst == ignoredResult()) {
650 generator.emitNode(ignoredResult(), m_expr.get());
651 return 0;
652 }
653 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
654 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
655}
656
657// ------------------------------ PrefixResolveNode ----------------------------------
658
659RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
660{
661 if (RegisterID* local = generator.registerForLocal(m_ident)) {
662 if (generator.isLocalConstant(m_ident)) {
663 if (dst == ignoredResult())
664 return 0;
665 RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
666 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get());
667 }
668
669 emitPreIncOrDec(generator, local, m_operator);
670 return generator.moveToDestinationIfNeeded(dst, local);
671 }
672
673 int index = 0;
674 size_t depth = 0;
675 JSValue* globalObject = 0;
676 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
677 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
678 emitPreIncOrDec(generator, propDst.get(), m_operator);
679 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
680 return generator.moveToDestinationIfNeeded(dst, propDst.get());
681 }
682
683 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
684 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
685 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
686 emitPreIncOrDec(generator, propDst.get(), m_operator);
687 generator.emitPutById(base.get(), m_ident, propDst.get());
688 return generator.moveToDestinationIfNeeded(dst, propDst.get());
689}
690
691// ------------------------------ PrefixBracketNode ----------------------------------
692
693RegisterID* PrefixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
694{
695 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
696 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
697 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
698
699 generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset);
700 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
701 if (m_operator == OpPlusPlus)
702 generator.emitPreInc(value);
703 else
704 generator.emitPreDec(value);
705 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
706 generator.emitPutByVal(base.get(), property.get(), value);
707 return generator.moveToDestinationIfNeeded(dst, propDst.get());
708}
709
710// ------------------------------ PrefixDotNode ----------------------------------
711
712RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
713{
714 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
715 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
716
717 generator.emitExpressionInfo(m_divot + m_subexpressionDivotOffset, m_subexpressionStartOffset, m_endOffset - m_subexpressionDivotOffset);
718 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
719 if (m_operator == OpPlusPlus)
720 generator.emitPreInc(value);
721 else
722 generator.emitPreDec(value);
723 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
724 generator.emitPutById(base.get(), m_ident, value);
725 return generator.moveToDestinationIfNeeded(dst, propDst.get());
726}
727
728// ------------------------------ PrefixErrorNode -----------------------------------
729
730RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
731{
732 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.");
733}
734
735// ------------------------------ Unary Operation Nodes -----------------------------------
736
737RegisterID* UnaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
738{
739 RegisterID* src = generator.emitNode(m_expr.get());
740 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src);
741}
742
743// ------------------------------ Binary Operation Nodes -----------------------------------
744
745RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
746{
747 OpcodeID opcode = this->opcode();
748 if (opcode == op_neq) {
749 if (m_expr1->isNull() || m_expr2->isNull()) {
750 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
751 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
752 }
753 }
754
755 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
756 RegisterID* src2 = generator.emitNode(m_expr2.get());
757 return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2);
758}
759
760RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
761{
762 if (m_expr1->isNull() || m_expr2->isNull()) {
763 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
764 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
765 }
766
767 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
768 RegisterID* src2 = generator.emitNode(m_expr2.get());
769 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
770}
771
772RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
773{
774 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
775 RegisterID* src2 = generator.emitNode(m_expr2.get());
776 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
777}
778
779RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
780{
781 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
782 RegisterID* src2 = generator.emitNode(m_expr2.get());
783 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get());
784}
785
786RegisterID* ThrowableBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
787{
788 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
789 RegisterID* src2 = generator.emitNode(m_expr2.get());
790 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
791 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2);
792}
793
794RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
795{
796 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
797 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
798
799 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
800 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalExec()->propertyNames().prototype);
801
802 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
803 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
804}
805
806// ------------------------------ Binary Logical Nodes ----------------------------
807
808RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
809{
810 RefPtr<RegisterID> temp = generator.tempDestination(dst);
811 RefPtr<LabelID> target = generator.newLabel();
812
813 generator.emitNode(temp.get(), m_expr1.get());
814 if (m_operator == OpLogicalAnd)
815 generator.emitJumpIfFalse(temp.get(), target.get());
816 else
817 generator.emitJumpIfTrue(temp.get(), target.get());
818 generator.emitNode(temp.get(), m_expr2.get());
819 generator.emitLabel(target.get());
820
821 return generator.moveToDestinationIfNeeded(dst, temp.get());
822}
823
824// ------------------------------ ConditionalNode ------------------------------
825
826RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
827{
828 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
829 RefPtr<LabelID> beforeElse = generator.newLabel();
830 RefPtr<LabelID> afterElse = generator.newLabel();
831
832 RegisterID* cond = generator.emitNode(m_logical.get());
833 generator.emitJumpIfFalse(cond, beforeElse.get());
834
835 generator.emitNode(newDst.get(), m_expr1.get());
836 generator.emitJump(afterElse.get());
837
838 generator.emitLabel(beforeElse.get());
839 generator.emitNode(newDst.get(), m_expr2.get());
840
841 generator.emitLabel(afterElse.get());
842
843 return newDst.get();
844}
845
846// ------------------------------ ReadModifyResolveNode -----------------------------------
847
848// FIXME: should this be moved to be a method on CodeGenerator?
849static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper)
850{
851 OpcodeID opcode;
852 switch (oper) {
853 case OpMultEq:
854 opcode = op_mul;
855 break;
856 case OpDivEq:
857 opcode = op_div;
858 break;
859 case OpPlusEq:
860 opcode = op_add;
861 break;
862 case OpMinusEq:
863 opcode = op_sub;
864 break;
865 case OpLShift:
866 opcode = op_lshift;
867 break;
868 case OpRShift:
869 opcode = op_rshift;
870 break;
871 case OpURShift:
872 opcode = op_urshift;
873 break;
874 case OpAndEq:
875 opcode = op_bitand;
876 break;
877 case OpXOrEq:
878 opcode = op_bitxor;
879 break;
880 case OpOrEq:
881 opcode = op_bitor;
882 break;
883 case OpModEq:
884 opcode = op_mod;
885 break;
886 default:
887 ASSERT_NOT_REACHED();
888 return dst;
889 }
890
891 return generator.emitBinaryOp(opcode, dst, src1, src2);
892}
893
894RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
895{
896 if (RegisterID* local = generator.registerForLocal(m_ident)) {
897 if (generator.isLocalConstant(m_ident)) {
898 RegisterID* src2 = generator.emitNode(m_right.get());
899 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator);
900 }
901
902 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
903 RefPtr<RegisterID> result = generator.newTemporary();
904 generator.emitMove(result.get(), local);
905 RegisterID* src2 = generator.emitNode(m_right.get());
906 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator);
907 generator.emitMove(local, result.get());
908 return generator.moveToDestinationIfNeeded(dst, result.get());
909 }
910
911 RegisterID* src2 = generator.emitNode(m_right.get());
912 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator);
913 return generator.moveToDestinationIfNeeded(dst, result);
914 }
915
916 int index = 0;
917 size_t depth = 0;
918 JSValue* globalObject = 0;
919 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
920 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
921 RegisterID* src2 = generator.emitNode(m_right.get());
922 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
923 generator.emitPutScopedVar(depth, index, result, globalObject);
924 return result;
925 }
926
927 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
928 generator.emitExpressionInfo(m_divot - m_startOffset + m_ident.size(), m_ident.size(), 0);
929 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
930 RegisterID* src2 = generator.emitNode(m_right.get());
931 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
932 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
933 return generator.emitPutById(base.get(), m_ident, result);
934}
935
936// ------------------------------ AssignResolveNode -----------------------------------
937
938RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
939{
940 if (RegisterID* local = generator.registerForLocal(m_ident)) {
941 if (generator.isLocalConstant(m_ident))
942 return generator.emitNode(dst, m_right.get());
943
944 RegisterID* result = generator.emitNode(local, m_right.get());
945 return generator.moveToDestinationIfNeeded(dst, result);
946 }
947
948 int index = 0;
949 size_t depth = 0;
950 JSValue* globalObject = 0;
951 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
952 if (dst == ignoredResult())
953 dst = 0;
954 RegisterID* value = generator.emitNode(dst, m_right.get());
955 generator.emitPutScopedVar(depth, index, value, globalObject);
956 return value;
957 }
958
959 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
960 if (dst == ignoredResult())
961 dst = 0;
962 RegisterID* value = generator.emitNode(dst, m_right.get());
963 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
964 return generator.emitPutById(base.get(), m_ident, value);
965}
966
967// ------------------------------ AssignDotNode -----------------------------------
968
969RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
970{
971 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
972 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
973 RegisterID* result = generator.emitNode(value.get(), m_right.get());
974 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
975 generator.emitPutById(base.get(), m_ident, result);
976 return generator.moveToDestinationIfNeeded(dst, result);
977}
978
979// ------------------------------ ReadModifyDotNode -----------------------------------
980
981RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
982{
983 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
984
985 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
986 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
987 RegisterID* change = generator.emitNode(m_right.get());
988 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
989
990 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
991 return generator.emitPutById(base.get(), m_ident, updatedValue);
992}
993
994// ------------------------------ AssignErrorNode -----------------------------------
995
996RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
997{
998 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
999}
1000
1001// ------------------------------ AssignBracketNode -----------------------------------
1002
1003RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1004{
1005 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1006 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1007 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1008 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1009
1010 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1011 generator.emitPutByVal(base.get(), property.get(), result);
1012 return generator.moveToDestinationIfNeeded(dst, result);
1013}
1014
1015RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1016{
1017 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1018 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1019
1020 generator.emitExpressionInfo(m_divot - m_subexpressionDivotOffset, m_startOffset - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1021 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1022 RegisterID* change = generator.emitNode(m_right.get());
1023 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator);
1024
1025 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1026 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1027
1028 return updatedValue;
1029}
1030
1031// ------------------------------ CommaNode ------------------------------------
1032
1033RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1034{
1035 generator.emitNode(ignoredResult(), m_expr1.get());
1036 return generator.emitNode(dst, m_expr2.get());
1037}
1038
1039// ------------------------------ ConstDeclNode ----------------------------------
1040
1041ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
1042 : ExpressionNode(globalData)
1043 , m_ident(ident)
1044 , m_init(init)
1045{
1046}
1047
1048RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
1049{
1050 if (RegisterID* local = generator.registerForLocalConstInit(m_ident)) {
1051 if (!m_init)
1052 return local;
1053
1054 return generator.emitNode(local, m_init.get());
1055 }
1056
1057 // FIXME: While this code should only be hit in eval code, it will potentially
1058 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1059 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1060 RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
1061 return generator.emitPutById(base.get(), m_ident, value);
1062}
1063
1064RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
1065{
1066 RegisterID* result = 0;
1067 for (ConstDeclNode* n = this; n; n = n->m_next.get())
1068 result = n->emitCodeSingle(generator);
1069
1070 return result;
1071}
1072
1073// ------------------------------ ConstStatementNode -----------------------------
1074
1075RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1076{
1077 return generator.emitNode(m_next.get());
1078}
1079
1080// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
1081
1082static inline RegisterID* statementListEmitCode(StatementVector& statements, CodeGenerator& generator, RegisterID* dst = 0)
1083{
1084 StatementVector::iterator end = statements.end();
1085 for (StatementVector::iterator it = statements.begin(); it != end; ++it) {
1086 StatementNode* n = it->get();
1087 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
1088 generator.emitNode(dst, n);
1089 }
1090 return 0;
1091}
1092
1093static inline void statementListPushFIFO(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1094{
1095 StatementVector::iterator it = statements.end();
1096 StatementVector::iterator begin = statements.begin();
1097 while (it != begin) {
1098 --it;
1099 stack.append((*it).get());
1100 }
1101}
1102
1103static inline Node* statementListInitializeVariableAccessStack(StatementVector& statements, DeclarationStacks::NodeStack& stack)
1104{
1105 if (statements.isEmpty())
1106 return 0;
1107
1108 StatementVector::iterator it = statements.end();
1109 StatementVector::iterator begin = statements.begin();
1110 StatementVector::iterator beginPlusOne = begin + 1;
1111
1112 while (it != beginPlusOne) {
1113 --it;
1114 stack.append((*it).get());
1115 }
1116
1117 return (*begin).get();
1118}
1119
1120// ------------------------------ BlockNode ------------------------------------
1121
1122BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
1123 : StatementNode(globalData)
1124{
1125 if (children)
1126 children->releaseContentsIntoVector(m_children);
1127}
1128
1129RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1130{
1131 return statementListEmitCode(m_children, generator, dst);
1132}
1133
1134// ------------------------------ EmptyStatementNode ---------------------------
1135
1136RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
1137{
1138 return dst;
1139}
1140
1141// ------------------------------ DebuggerStatementNode ---------------------------
1142
1143RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1144{
1145 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1146 return dst;
1147}
1148
1149// ------------------------------ ExprStatementNode ----------------------------
1150
1151RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1152{
1153 ASSERT(m_expr);
1154 return generator.emitNode(dst, m_expr.get());
1155}
1156
1157// ------------------------------ VarStatementNode ----------------------------
1158
1159RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1160{
1161 ASSERT(m_expr);
1162 return generator.emitNode(m_expr.get());
1163}
1164
1165// ------------------------------ IfNode ---------------------------------------
1166
1167RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1168{
1169 RefPtr<LabelID> afterThen = generator.newLabel();
1170
1171 RegisterID* cond = generator.emitNode(m_condition.get());
1172 generator.emitJumpIfFalse(cond, afterThen.get());
1173
1174 if (!m_ifBlock->isBlock())
1175 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1176
1177 generator.emitNode(dst, m_ifBlock.get());
1178 generator.emitLabel(afterThen.get());
1179
1180 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1181 return 0;
1182}
1183
1184RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1185{
1186 RefPtr<LabelID> beforeElse = generator.newLabel();
1187 RefPtr<LabelID> afterElse = generator.newLabel();
1188
1189 RegisterID* cond = generator.emitNode(m_condition.get());
1190 generator.emitJumpIfFalse(cond, beforeElse.get());
1191
1192 if (!m_ifBlock->isBlock())
1193 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1194
1195 generator.emitNode(dst, m_ifBlock.get());
1196 generator.emitJump(afterElse.get());
1197
1198 generator.emitLabel(beforeElse.get());
1199 generator.emitNode(dst, m_elseBlock.get());
1200
1201 generator.emitLabel(afterElse.get());
1202
1203 // FIXME: This should return the last statement exectuted so that it can be returned as a Completion
1204 return 0;
1205}
1206
1207// ------------------------------ DoWhileNode ----------------------------------
1208
1209RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1210{
1211 RefPtr<LabelID> topOfLoop = generator.newLabel();
1212 generator.emitLabel(topOfLoop.get());
1213
1214 if (!m_statement->isBlock())
1215 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1216
1217 RefPtr<LabelID> continueTarget = generator.newLabel();
1218 RefPtr<LabelID> breakTarget = generator.newLabel();
1219
1220 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1221 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1222 generator.popJumpContext();
1223
1224 generator.emitLabel(continueTarget.get());
1225 RegisterID* cond = generator.emitNode(m_expr.get());
1226 generator.emitJumpIfTrue(cond, topOfLoop.get());
1227
1228 generator.emitLabel(breakTarget.get());
1229 return result.get();
1230}
1231
1232// ------------------------------ WhileNode ------------------------------------
1233
1234RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1235{
1236 RefPtr<LabelID> topOfLoop = generator.newLabel();
1237 RefPtr<LabelID> continueTarget = generator.newLabel();
1238 RefPtr<LabelID> breakTarget = generator.newLabel();
1239
1240 generator.emitJump(continueTarget.get());
1241 generator.emitLabel(topOfLoop.get());
1242
1243 if (!m_statement->isBlock())
1244 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1245
1246 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1247 generator.emitNode(dst, m_statement.get());
1248 generator.popJumpContext();
1249
1250 generator.emitLabel(continueTarget.get());
1251 RegisterID* cond = generator.emitNode(m_expr.get());
1252 generator.emitJumpIfTrue(cond, topOfLoop.get());
1253
1254 generator.emitLabel(breakTarget.get());
1255
1256 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1257 return 0;
1258}
1259
1260// ------------------------------ ForNode --------------------------------------
1261
1262RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1263{
1264 if (m_expr1)
1265 generator.emitNode(ignoredResult(), m_expr1.get());
1266
1267 RefPtr<LabelID> topOfLoop = generator.newLabel();
1268 RefPtr<LabelID> beforeCondition = generator.newLabel();
1269 RefPtr<LabelID> continueTarget = generator.newLabel();
1270 RefPtr<LabelID> breakTarget = generator.newLabel();
1271 generator.emitJump(beforeCondition.get());
1272
1273 generator.emitLabel(topOfLoop.get());
1274 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1275 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1276 generator.popJumpContext();
1277 generator.emitLabel(continueTarget.get());
1278 if (m_expr3)
1279 generator.emitNode(ignoredResult(), m_expr3.get());
1280
1281 generator.emitLabel(beforeCondition.get());
1282 if (m_expr2) {
1283 RegisterID* cond = generator.emitNode(m_expr2.get());
1284 generator.emitJumpIfTrue(cond, topOfLoop.get());
1285 } else {
1286 generator.emitJump(topOfLoop.get());
1287 }
1288
1289 if (!m_statement->isBlock())
1290 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1291
1292 generator.emitLabel(breakTarget.get());
1293 return result.get();
1294}
1295
1296// ------------------------------ ForInNode ------------------------------------
1297
1298ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
1299 : StatementNode(globalData)
1300 , m_init(0L)
1301 , m_lexpr(l)
1302 , m_expr(expr)
1303 , m_statement(statement)
1304 , m_identIsVarDecl(false)
1305{
1306}
1307
1308ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
1309 : StatementNode(globalData)
1310 , m_ident(ident)
1311 , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
1312 , m_expr(expr)
1313 , m_statement(statement)
1314 , m_identIsVarDecl(true)
1315{
1316 if (in) {
1317 AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
1318 node->setExceptionSourceRange(divot, divot - startOffset, endOffset - divot);
1319 m_init = node;
1320 }
1321 // for( var foo = bar in baz )
1322}
1323
1324RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1325{
1326 if (!m_lexpr->isLocation())
1327 return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
1328 RefPtr<LabelID> loopStart = generator.newLabel();
1329 RefPtr<LabelID> continueTarget = generator.newLabel();
1330 RefPtr<LabelID> breakTarget = generator.newLabel();
1331
1332 if (m_init)
1333 generator.emitNode(ignoredResult(), m_init.get());
1334 RegisterID* forInBase = generator.emitNode(m_expr.get());
1335 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1336 generator.emitJump(continueTarget.get());
1337 generator.emitLabel(loopStart.get());
1338 RegisterID* propertyName;
1339 if (m_lexpr->isResolveNode()) {
1340 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
1341 propertyName = generator.registerForLocal(ident);
1342 if (!propertyName) {
1343 propertyName = generator.newTemporary();
1344 RefPtr<RegisterID> protect = propertyName;
1345 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1346
1347 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1348 generator.emitPutById(base, ident, propertyName);
1349 }
1350 } else if (m_lexpr->isDotAccessorNode()) {
1351 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
1352 const Identifier& ident = assignNode->identifier();
1353 propertyName = generator.newTemporary();
1354 RefPtr<RegisterID> protect = propertyName;
1355 RegisterID* base = generator.emitNode(assignNode->base());
1356
1357 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1358 generator.emitPutById(base, ident, propertyName);
1359 } else {
1360 ASSERT(m_lexpr->isBracketAccessorNode());
1361 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
1362 propertyName = generator.newTemporary();
1363 RefPtr<RegisterID> protect = propertyName;
1364 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1365 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1366
1367 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1368 generator.emitPutByVal(base.get(), subscript, propertyName);
1369 }
1370
1371 generator.pushJumpContext(&m_labelStack, continueTarget.get(), breakTarget.get(), true);
1372 generator.emitNode(dst, m_statement.get());
1373 generator.popJumpContext();
1374
1375 if (!m_statement->isBlock())
1376 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1377
1378 generator.emitLabel(continueTarget.get());
1379 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1380 generator.emitLabel(breakTarget.get());
1381 return dst;
1382}
1383
1384// ------------------------------ ContinueNode ---------------------------------
1385
1386// ECMA 12.7
1387RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1388{
1389 if (!generator.inContinueContext())
1390 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1391
1392 JumpContext* targetContext = generator.jumpContextForContinue(m_ident);
1393
1394 if (!targetContext) {
1395 if (m_ident.isEmpty())
1396 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1397 else
1398 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1399 }
1400
1401 if (!targetContext->continueTarget)
1402 return emitThrowError(generator, SyntaxError, "Invalid continue statement.");
1403
1404 generator.emitJumpScopes(targetContext->continueTarget, targetContext->scopeDepth);
1405
1406 return dst;
1407}
1408
1409// ------------------------------ BreakNode ------------------------------------
1410
1411// ECMA 12.8
1412RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1413{
1414 if (!generator.inJumpContext())
1415 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1416
1417 JumpContext* targetContext = generator.jumpContextForBreak(m_ident);
1418
1419 if (!targetContext) {
1420 if (m_ident.isEmpty())
1421 return emitThrowError(generator, SyntaxError, "Invalid break statement.");
1422 else
1423 return emitThrowError(generator, SyntaxError, "Label %s not found.", m_ident);
1424 }
1425
1426 ASSERT(targetContext->breakTarget);
1427
1428 generator.emitJumpScopes(targetContext->breakTarget, targetContext->scopeDepth);
1429
1430 return dst;
1431}
1432
1433// ------------------------------ ReturnNode -----------------------------------
1434
1435RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1436{
1437 if (generator.codeType() != FunctionCode)
1438 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
1439
1440 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
1441 if (generator.scopeDepth()) {
1442 RefPtr<LabelID> l0 = generator.newLabel();
1443 generator.emitJumpScopes(l0.get(), 0);
1444 generator.emitLabel(l0.get());
1445 }
1446 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1447 return generator.emitReturn(r0);
1448}
1449
1450// ------------------------------ WithNode -------------------------------------
1451
1452RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1453{
1454 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
1455 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
1456 generator.emitPushScope(scope.get());
1457 RegisterID* result = generator.emitNode(dst, m_statement.get());
1458 generator.emitPopScope();
1459 return result;
1460}
1461
1462// ------------------------------ CaseBlockNode --------------------------------
1463enum SwitchKind {
1464 SwitchUnset = 0,
1465 SwitchNumber = 1,
1466 SwitchString = 2,
1467 SwitchNeither = 3
1468};
1469
1470static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
1471{
1472 for (; list; list = list->getNext()) {
1473 ExpressionNode* clauseExpression = list->getClause()->expr();
1474 literalVector.append(clauseExpression);
1475 if (clauseExpression->isNumber()) {
1476 double value = static_cast<NumberNode*>(clauseExpression)->value();
1477 if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) {
1478 typeForTable = SwitchNeither;
1479 break;
1480 }
1481 int32_t intVal = static_cast<int32_t>(value);
1482 ASSERT(intVal == value);
1483 if (intVal < min_num)
1484 min_num = intVal;
1485 if (intVal > max_num)
1486 max_num = intVal;
1487 typeForTable = SwitchNumber;
1488 continue;
1489 }
1490 if (clauseExpression->isString()) {
1491 if (typeForTable & ~SwitchString) {
1492 typeForTable = SwitchNeither;
1493 break;
1494 }
1495 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
1496 if (singleCharacterSwitch &= value.size() == 1) {
1497 int32_t intVal = value.rep()->data()[0];
1498 if (intVal < min_num)
1499 min_num = intVal;
1500 if (intVal > max_num)
1501 max_num = intVal;
1502 }
1503 typeForTable = SwitchString;
1504 continue;
1505 }
1506 typeForTable = SwitchNeither;
1507 break;
1508 }
1509}
1510
1511SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
1512{
1513 SwitchKind typeForTable = SwitchUnset;
1514 bool singleCharacterSwitch = true;
1515
1516 processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1517 processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1518
1519 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
1520 return SwitchInfo::SwitchNone;
1521
1522 if (typeForTable == SwitchNumber) {
1523 int32_t range = max_num - min_num;
1524 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1525 return SwitchInfo::SwitchImmediate;
1526 return SwitchInfo::SwitchNone;
1527 }
1528
1529 ASSERT(typeForTable == SwitchString);
1530
1531 if (singleCharacterSwitch) {
1532 int32_t range = max_num - min_num;
1533 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1534 return SwitchInfo::SwitchCharacter;
1535 }
1536
1537 return SwitchInfo::SwitchString;
1538}
1539
1540RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1541{
1542 RefPtr<LabelID> defaultLabel;
1543 Vector<RefPtr<LabelID>, 8> labelVector;
1544 Vector<ExpressionNode*, 8> literalVector;
1545 int32_t min_num = std::numeric_limits<int32_t>::max();
1546 int32_t max_num = std::numeric_limits<int32_t>::min();
1547 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
1548
1549 if (switchType != SwitchInfo::SwitchNone) {
1550 // Prepare the various labels
1551 for (uint32_t i = 0; i < literalVector.size(); i++)
1552 labelVector.append(generator.newLabel());
1553 defaultLabel = generator.newLabel();
1554 generator.beginSwitch(switchExpression, switchType);
1555 } else {
1556 // Setup jumps
1557 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1558 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1559 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1560 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression);
1561 labelVector.append(generator.newLabel());
1562 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1563 }
1564
1565 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1566 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1567 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1568 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression);
1569 labelVector.append(generator.newLabel());
1570 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1571 }
1572 defaultLabel = generator.newLabel();
1573 generator.emitJump(defaultLabel.get());
1574 }
1575
1576 RegisterID* result = 0;
1577
1578 size_t i = 0;
1579 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
1580 generator.emitLabel(labelVector[i++].get());
1581 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1582 }
1583
1584 if (m_defaultClause) {
1585 generator.emitLabel(defaultLabel.get());
1586 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
1587 }
1588
1589 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
1590 generator.emitLabel(labelVector[i++].get());
1591 result = statementListEmitCode(list->getClause()->children(), generator, dst);
1592 }
1593 if (!m_defaultClause)
1594 generator.emitLabel(defaultLabel.get());
1595
1596 ASSERT(i == labelVector.size());
1597 if (switchType != SwitchInfo::SwitchNone) {
1598 ASSERT(labelVector.size() == literalVector.size());
1599 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
1600 }
1601 return result;
1602}
1603
1604// ------------------------------ SwitchNode -----------------------------------
1605
1606RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1607{
1608 RefPtr<LabelID> breakTarget = generator.newLabel();
1609
1610 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
1611 generator.pushJumpContext(&m_labelStack, 0, breakTarget.get(), true);
1612 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
1613 generator.popJumpContext();
1614
1615 generator.emitLabel(breakTarget.get());
1616
1617 return r1;
1618}
1619
1620// ------------------------------ LabelNode ------------------------------------
1621
1622RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1623{
1624 if (generator.jumpContextForBreak(m_label))
1625 return emitThrowError(generator, SyntaxError, "Duplicated label %s found.", m_label);
1626
1627 RefPtr<LabelID> l0 = generator.newLabel();
1628 m_labelStack.push(m_label);
1629 generator.pushJumpContext(&m_labelStack, 0, l0.get(), false);
1630
1631 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
1632
1633 generator.popJumpContext();
1634 m_labelStack.pop();
1635
1636 generator.emitLabel(l0.get());
1637 return r0;
1638}
1639
1640// ------------------------------ ThrowNode ------------------------------------
1641
1642RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1643{
1644 RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
1645 generator.emitExpressionInfo(m_divot, m_startOffset, m_endOffset);
1646 generator.emitThrow(expr.get());
1647 return dst;
1648}
1649
1650// ------------------------------ TryNode --------------------------------------
1651
1652RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1653{
1654 RefPtr<LabelID> tryStartLabel = generator.newLabel();
1655 RefPtr<LabelID> tryEndLabel = generator.newLabel();
1656 RefPtr<LabelID> finallyStart;
1657 RefPtr<RegisterID> finallyReturnAddr;
1658 if (m_finallyBlock) {
1659 finallyStart = generator.newLabel();
1660 finallyReturnAddr = generator.newTemporary();
1661 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
1662 }
1663 generator.emitLabel(tryStartLabel.get());
1664 generator.emitNode(dst, m_tryBlock.get());
1665 generator.emitLabel(tryEndLabel.get());
1666
1667 if (m_catchBlock) {
1668 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
1669 generator.emitJump(handlerEndLabel.get());
1670 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
1671 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
1672 generator.emitNode(dst, m_catchBlock.get());
1673 generator.emitPopScope();
1674 generator.emitLabel(handlerEndLabel.get());
1675 }
1676
1677 if (m_finallyBlock) {
1678 generator.popFinallyContext();
1679 // there may be important registers live at the time we jump
1680 // to a finally block (such as for a return or throw) so we
1681 // ref the highest register ever used as a conservative
1682 // approach to not clobbering anything important
1683 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
1684 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
1685 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1686 // Use a label to record the subtle fact that sret will return to the
1687 // next instruction. sret is the only way to jump without an explicit label.
1688 generator.emitLabel(generator.newLabel().get());
1689 generator.emitJump(finallyEndLabel.get());
1690
1691 // Finally block for exception path
1692 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
1693 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1694 // Use a label to record the subtle fact that sret will return to the
1695 // next instruction. sret is the only way to jump without an explicit label.
1696 generator.emitLabel(generator.newLabel().get());
1697 generator.emitThrow(tempExceptionRegister.get());
1698
1699 // emit the finally block itself
1700 generator.emitLabel(finallyStart.get());
1701 generator.emitNode(dst, m_finallyBlock.get());
1702 generator.emitSubroutineReturn(finallyReturnAddr.get());
1703
1704 generator.emitLabel(finallyEndLabel.get());
1705 }
1706
1707 return dst;
1708}
1709
1710
1711// ------------------------------ ScopeNode -----------------------------
1712
1713ScopeNode::ScopeNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure, int numConstants)
1714 : BlockNode(globalData, children)
1715 , m_sourceURL(globalData->parser->sourceURL())
1716 , m_sourceId(globalData->parser->sourceId())
1717 , m_usesEval(usesEval)
1718 , m_needsClosure(needsClosure)
1719 , m_numConstants(numConstants)
1720{
1721 if (varStack)
1722 m_varStack = *varStack;
1723 if (funcStack)
1724 m_functionStack = *funcStack;
1725
1726 SCOPENODE_SAMPLING_notifyOfScope(globalData->machine->m_sampler);
1727}
1728
1729// ------------------------------ ProgramNode -----------------------------
1730
1731ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, SourceProvider* sourceProvider, bool usesEval, bool needsClosure, int numConstants)
1732 : ScopeNode(globalData, children, varStack, funcStack, usesEval, needsClosure, numConstants)
1733 , m_sourceProvider(sourceProvider)
1734{
1735}
1736
1737ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, SourceProvider* sourceProvider, bool usesEval, bool needsClosure, int numConstants)
1738{
1739 return new ProgramNode(globalData, children, varStack, funcStack, sourceProvider, usesEval, needsClosure, numConstants);
1740}
1741
1742// ------------------------------ EvalNode -----------------------------
1743
1744EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, SourceProvider* sourceProvider, bool usesEval, bool needsClosure, int numConstants)
1745 : ScopeNode(globalData, children, varStack, funcStack, usesEval, needsClosure, numConstants)
1746 , m_sourceProvider(sourceProvider)
1747{
1748}
1749
1750RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
1751{
1752 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1753
1754 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1755 generator.emitLoad(dstRegister.get(), jsUndefined());
1756 statementListEmitCode(m_children, generator, dstRegister.get());
1757
1758 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1759 generator.emitEnd(dstRegister.get());
1760 return 0;
1761}
1762
1763void EvalNode::generateCode(ScopeChainNode* sc)
1764{
1765 ScopeChain scopeChain(sc);
1766 JSGlobalObject* globalObject = scopeChain.globalObject();
1767
1768 SymbolTable symbolTable;
1769 ASSERT(m_sourceProvider);
1770 m_code.set(new EvalCodeBlock(this, globalObject, m_sourceProvider));
1771
1772 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get());
1773 generator.generate();
1774}
1775
1776EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, SourceProvider* sourceProvider, bool usesEval, bool needsClosure, int numConstants)
1777{
1778 return new EvalNode(globalData, children, varStack, funcStack, sourceProvider, usesEval, needsClosure, numConstants);
1779}
1780
1781// ------------------------------ FunctionBodyNode -----------------------------
1782
1783FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure, int numConstants)
1784 : ScopeNode(globalData, children, varStack, funcStack, usesEval, needsClosure, numConstants)
1785 , m_refCount(0)
1786{
1787}
1788
1789void FunctionBodyNode::mark()
1790{
1791 if (m_code)
1792 m_code->mark();
1793}
1794
1795FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, bool usesEval, bool needsClosure, int numConstants)
1796{
1797 return new FunctionBodyNode(globalData, children, varStack, funcStack, usesEval, needsClosure, numConstants);
1798}
1799
1800FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, SourceProvider*, bool usesEval, bool needsClosure, int numConstants)
1801{
1802 return new FunctionBodyNode(globalData, children, varStack, funcStack, usesEval, needsClosure, numConstants);
1803}
1804
1805void FunctionBodyNode::generateCode(ScopeChainNode* sc)
1806{
1807 ScopeChain scopeChain(sc);
1808 JSGlobalObject* globalObject = scopeChain.globalObject();
1809
1810 ASSERT(m_source.sourceProvider());
1811 m_code.set(new CodeBlock(this, FunctionCode, m_source.sourceProvider(), m_source.startOffset()));
1812
1813 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get());
1814 generator.generate();
1815}
1816
1817RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
1818{
1819 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
1820 statementListEmitCode(m_children, generator);
1821 if (!m_children.size() || !m_children.last()->isReturnNode()) {
1822 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
1823 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1824 generator.emitReturn(r0);
1825 }
1826 return 0;
1827}
1828
1829RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
1830{
1831 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1832
1833 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1834 generator.emitLoad(dstRegister.get(), jsUndefined());
1835 statementListEmitCode(m_children, generator, dstRegister.get());
1836
1837 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1838 generator.emitEnd(dstRegister.get());
1839 return 0;
1840}
1841
1842void ProgramNode::generateCode(ScopeChainNode* sc)
1843{
1844 ScopeChain scopeChain(sc);
1845 JSGlobalObject* globalObject = scopeChain.globalObject();
1846
1847 ASSERT(m_sourceProvider);
1848 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, m_sourceProvider));
1849
1850 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack);
1851 generator.generate();
1852}
1853
1854UString FunctionBodyNode::paramString() const
1855{
1856 UString s("");
1857 size_t count = m_parameters.size();
1858 for (size_t pos = 0; pos < count; ++pos) {
1859 if (!s.isEmpty())
1860 s += ", ";
1861 s += m_parameters[pos].ustring();
1862 }
1863
1864 return s;
1865}
1866
1867// ------------------------------ FuncDeclNode ---------------------------------
1868
1869void FuncDeclNode::addParams()
1870{
1871 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
1872 m_body->parameters().append(p->ident());
1873}
1874
1875JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1876{
1877 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
1878
1879 JSObject* proto = constructEmptyObject(exec);
1880 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1881 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1882 return func;
1883}
1884
1885RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
1886{
1887 return dst;
1888}
1889
1890// ------------------------------ FuncExprNode ---------------------------------
1891
1892RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1893{
1894 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
1895}
1896
1897JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
1898{
1899 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
1900 JSObject* proto = constructEmptyObject(exec);
1901 proto->putDirect(exec->propertyNames().constructor, func, DontEnum);
1902 func->putDirect(exec->propertyNames().prototype, proto, DontDelete);
1903
1904 /*
1905 The Identifier in a FunctionExpression can be referenced from inside
1906 the FunctionExpression's FunctionBody to allow the function to call
1907 itself recursively. However, unlike in a FunctionDeclaration, the
1908 Identifier in a FunctionExpression cannot be referenced from and
1909 does not affect the scope enclosing the FunctionExpression.
1910 */
1911
1912 if (!m_ident.isNull()) {
1913 JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
1914 func->scope().push(functionScopeObject);
1915 }
1916
1917 return func;
1918}
1919
1920// ECMA 13
1921void FuncExprNode::addParams()
1922{
1923 for (ParameterNode* p = m_parameter.get(); p; p = p->nextParam())
1924 m_body->parameters().append(p->ident());
1925}
1926
1927} // namespace JSC
Note: See TracBrowser for help on using the repository browser.