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

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

2008-10-24 Cameron Zwarich <[email protected]>

Reviewed by Maciej Stachowiak.

Bug 21862: Create JSFunction prototype property lazily
<https://bugs.webkit.org/show_bug.cgi?id=21862>

This is a 1.5% speedup on SunSpider and a 1.4% speedup on the V8
benchmark suite, including a 3.8% speedup on Earley-Boyer.

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