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

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

2008-11-11 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler.


Fixed https://bugs.webkit.org/show_bug.cgi?id=22174
Simplified op_call by nixing its responsibility for moving the value of
"this" into the first argument slot.

Instead, the caller emits an explicit load or mov instruction, or relies
on implicit knowledge that "this" is already in the first argument slot.
As a result, two operands to op_call are gone: firstArg and thisVal.


SunSpider and v8 tests show no change in bytecode or CTI.

  • VM/CTI.cpp: (JSC::CTI::compileOpCallSetupArgs): (JSC::CTI::compileOpCallEvalSetupArgs): (JSC::CTI::compileOpConstructSetupArgs): Split apart these three versions of setting up arguments to op_call, because they're more different than they are the same -- even more so with this patch.

(JSC::CTI::compileOpCall): Updated for the fact that op_construct doesn't
match op_call anymore.

(JSC::CTI::privateCompileMainPass):
(JSC::CTI::privateCompileSlowCases): Merged a few call cases. Updated
for changes mentioned above.

  • VM/CTI.h:
  • VM/CodeBlock.cpp: (JSC::CodeBlock::dump): Updated for new bytecode format of call / construct.
  • VM/Machine.cpp: (JSC::Machine::callEval): Updated for new bytecode format of call / construct.

(JSC::Machine::dumpCallFrame):
(JSC::Machine::dumpRegisters): Simplified these debugging functions,
taking advantage of the new call frame layout.

(JSC::Machine::execute): Fixed up the eval version of execute to be
friendlier to calls in the new format.

(JSC::Machine::privateExecute): Implemented the new call format in
bytecode.

(JSC::Machine::cti_op_call_NotJSFunction):
(JSC::Machine::cti_op_construct_JSConstruct):
(JSC::Machine::cti_op_construct_NotJSConstruct):
(JSC::Machine::cti_op_call_eval): Updated CTI helpers to match the new
call format.


Fixed a latent bug in stack overflow checking that is now hit because
the register layout has changed a bit -- namely: when throwing a stack
overflow exception inside an op_call helper, we need to account for the
fact that the current call frame is only half-constructed, and use the
parent call frame instead.

  • VM/Machine.h:
  • bytecompiler/CodeGenerator.cpp: (JSC::CodeGenerator::emitCall): (JSC::CodeGenerator::emitCallEval): (JSC::CodeGenerator::emitConstruct):
  • bytecompiler/CodeGenerator.h: Updated codegen to match the new call format.
  • parser/Nodes.cpp: (JSC::EvalFunctionCallNode::emitCode): (JSC::FunctionCallValueNode::emitCode): (JSC::FunctionCallResolveNode::emitCode): (JSC::FunctionCallBracketNode::emitCode): (JSC::FunctionCallDotNode::emitCode):
  • parser/Nodes.h: (JSC::ScopeNode::neededConstants): ditto

2008-11-10 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler.


Updated a test after fixing https://bugs.webkit.org/show_bug.cgi?id=22174
Simplified op_call by nixing its responsibility for moving the value of
"this" into the first argument slot.

  • fast/js/global-recursion-on-full-stack-expected.txt: This test passes a little differently now, because the register layout has changed. Specifically, the stack overflow now happens in the call to f() instead of the initiation of the <script> tag, so it is caught, and it does not log an exception to the console.
  • Property svn:eol-style set to native
File size: 90.5 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 "LabelScope.h"
34#include "Parser.h"
35#include "PropertyNameArray.h"
36#include "RegExpObject.h"
37#include "SamplingTool.h"
38#include "Debugger.h"
39#include "Lexer.h"
40#include "Operations.h"
41#include <math.h>
42#include <wtf/Assertions.h>
43#include <wtf/HashCountedSet.h>
44#include <wtf/HashSet.h>
45#include <wtf/MathExtras.h>
46#include <wtf/RefCountedLeakCounter.h>
47#include <wtf/Threading.h>
48
49using namespace WTF;
50
51namespace JSC {
52
53static void substitute(UString& string, const UString& substring) JSC_FAST_CALL;
54
55// ------------------------------ NodeReleaser --------------------------------
56
57class NodeReleaser : Noncopyable {
58public:
59 // Call this function inside the destructor of a class derived from Node.
60 // This will traverse the tree below this node, destroying all of those nodes,
61 // but without relying on recursion.
62 static void releaseAllNodes(ParserRefCounted* root);
63
64 // Call this on each node in a the releaseNodes virtual function.
65 // It gives the node to the NodeReleaser, which will then release the
66 // node later at the end of the releaseAllNodes process.
67 template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); }
68 void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); }
69
70private:
71 NodeReleaser() { }
72 ~NodeReleaser() { }
73
74 void adopt(PassRefPtr<ParserRefCounted>);
75 void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&);
76
77 typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector;
78 OwnPtr<NodeReleaseVector> m_vector;
79};
80
81void NodeReleaser::releaseAllNodes(ParserRefCounted* root)
82{
83 ASSERT(root);
84 NodeReleaser releaser;
85 root->releaseNodes(releaser);
86 if (!releaser.m_vector)
87 return;
88 // Note: The call to release.m_vector->size() is intentionally inside
89 // the loop, since calls to releaseNodes are expected to increase the size.
90 for (size_t i = 0; i < releaser.m_vector->size(); ++i) {
91 ParserRefCounted* node = (*releaser.m_vector)[i].get();
92 if (node->hasOneRef())
93 node->releaseNodes(releaser);
94 }
95}
96
97void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node)
98{
99 ASSERT(node);
100 if (!node->hasOneRef())
101 return;
102 if (!m_vector)
103 m_vector.set(new NodeReleaseVector);
104 m_vector->append(node);
105}
106
107void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode)
108{
109 // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode>
110 // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode
111 // and ParserRefCounted) unbalanced. It would be nice to fix this problem in
112 // a cleaner way -- perhaps we could remove the FunctionBodyNode reference
113 // count at some point.
114 RefPtr<Node> node = functionBodyNode;
115 functionBodyNode = 0;
116 adopt(node.release());
117}
118
119// ------------------------------ ParserRefCounted -----------------------------------------
120
121#ifndef NDEBUG
122static RefCountedLeakCounter parserRefCountedCounter("JSC::Node");
123#endif
124
125ParserRefCounted::ParserRefCounted(JSGlobalData* globalData)
126 : m_globalData(globalData)
127{
128#ifndef NDEBUG
129 parserRefCountedCounter.increment();
130#endif
131 if (!m_globalData->newParserObjects)
132 m_globalData->newParserObjects = new HashSet<ParserRefCounted*>;
133 m_globalData->newParserObjects->add(this);
134 ASSERT(m_globalData->newParserObjects->contains(this));
135}
136
137ParserRefCounted::~ParserRefCounted()
138{
139#ifndef NDEBUG
140 parserRefCountedCounter.decrement();
141#endif
142}
143
144void ParserRefCounted::releaseNodes(NodeReleaser&)
145{
146}
147
148void ParserRefCounted::ref()
149{
150 // bumping from 0 to 1 is just removing from the new nodes set
151 if (m_globalData->newParserObjects) {
152 HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this);
153 if (it != m_globalData->newParserObjects->end()) {
154 m_globalData->newParserObjects->remove(it);
155 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
156 return;
157 }
158 }
159
160 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
161
162 if (!m_globalData->parserObjectExtraRefCounts)
163 m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>;
164 m_globalData->parserObjectExtraRefCounts->add(this);
165}
166
167void ParserRefCounted::deref()
168{
169 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
170
171 if (!m_globalData->parserObjectExtraRefCounts) {
172 delete this;
173 return;
174 }
175
176 HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this);
177 if (it == m_globalData->parserObjectExtraRefCounts->end())
178 delete this;
179 else
180 m_globalData->parserObjectExtraRefCounts->remove(it);
181}
182
183bool ParserRefCounted::hasOneRef()
184{
185 if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) {
186 ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this));
187 return false;
188 }
189
190 ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this));
191
192 if (!m_globalData->parserObjectExtraRefCounts)
193 return true;
194
195 return !m_globalData->parserObjectExtraRefCounts->contains(this);
196}
197
198void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData)
199{
200 if (!globalData->newParserObjects)
201 return;
202
203#ifndef NDEBUG
204 HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end();
205 for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it)
206 ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it));
207#endif
208 deleteAllValues(*globalData->newParserObjects);
209 delete globalData->newParserObjects;
210 globalData->newParserObjects = 0;
211}
212
213// ------------------------------ Node --------------------------------
214
215Node::Node(JSGlobalData* globalData)
216 : ParserRefCounted(globalData)
217{
218 m_line = globalData->lexer->lineNo();
219}
220
221// ------------------------------ ThrowableExpressionData --------------------------------
222
223static void substitute(UString& string, const UString& substring)
224{
225 int position = string.find("%s");
226 ASSERT(position != -1);
227 UString newString = string.substr(0, position);
228 newString.append(substring);
229 newString.append(string.substr(position + 2));
230 string = newString;
231}
232
233RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg)
234{
235 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
236 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg));
237 generator.emitThrow(exception);
238 return exception;
239}
240
241RegisterID* ThrowableExpressionData::emitThrowError(CodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label)
242{
243 UString message = msg;
244 substitute(message, label.ustring());
245 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
246 RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message));
247 generator.emitThrow(exception);
248 return exception;
249}
250
251// ------------------------------ StatementNode --------------------------------
252
253StatementNode::StatementNode(JSGlobalData* globalData)
254 : Node(globalData)
255 , m_lastLine(-1)
256{
257}
258
259void StatementNode::setLoc(int firstLine, int lastLine)
260{
261 m_line = firstLine;
262 m_lastLine = lastLine;
263}
264
265// ------------------------------ SourceElements --------------------------------
266
267void SourceElements::append(PassRefPtr<StatementNode> statement)
268{
269 if (statement->isEmptyStatement())
270 return;
271
272 m_statements.append(statement);
273}
274
275// ------------------------------ NullNode -------------------------------------
276
277RegisterID* NullNode::emitCode(CodeGenerator& generator, RegisterID* dst)
278{
279 if (dst == ignoredResult())
280 return 0;
281 return generator.emitLoad(dst, jsNull());
282}
283
284// ------------------------------ BooleanNode ----------------------------------
285
286RegisterID* BooleanNode::emitCode(CodeGenerator& generator, RegisterID* dst)
287{
288 if (dst == ignoredResult())
289 return 0;
290 return generator.emitLoad(dst, m_value);
291}
292
293// ------------------------------ NumberNode -----------------------------------
294
295RegisterID* NumberNode::emitCode(CodeGenerator& generator, RegisterID* dst)
296{
297 if (dst == ignoredResult())
298 return 0;
299 return generator.emitLoad(dst, m_double);
300}
301
302// ------------------------------ StringNode -----------------------------------
303
304RegisterID* StringNode::emitCode(CodeGenerator& generator, RegisterID* dst)
305{
306 if (dst == ignoredResult())
307 return 0;
308 return generator.emitLoad(dst, m_value);
309}
310
311// ------------------------------ RegExpNode -----------------------------------
312
313RegisterID* RegExpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
314{
315 RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags);
316 if (!regExp->isValid())
317 return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str());
318 if (dst == ignoredResult())
319 return 0;
320 return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
321}
322
323// ------------------------------ ThisNode -------------------------------------
324
325RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
326{
327 if (dst == ignoredResult())
328 return 0;
329 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
330}
331
332// ------------------------------ ResolveNode ----------------------------------
333
334bool ResolveNode::isPure(CodeGenerator& generator) const
335{
336 return generator.isLocal(m_ident);
337}
338
339RegisterID* ResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
340{
341 if (RegisterID* local = generator.registerFor(m_ident)) {
342 if (dst == ignoredResult())
343 return 0;
344 return generator.moveToDestinationIfNeeded(dst, local);
345 }
346
347 generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
348 return generator.emitResolve(generator.finalDestination(dst), m_ident);
349}
350
351// ------------------------------ ElementNode ------------------------------------
352
353ElementNode::~ElementNode()
354{
355 NodeReleaser::releaseAllNodes(this);
356}
357
358void ElementNode::releaseNodes(NodeReleaser& releaser)
359{
360 releaser.release(m_next);
361 releaser.release(m_node);
362}
363
364// ------------------------------ ArrayNode ------------------------------------
365
366ArrayNode::~ArrayNode()
367{
368 NodeReleaser::releaseAllNodes(this);
369}
370
371void ArrayNode::releaseNodes(NodeReleaser& releaser)
372{
373 releaser.release(m_element);
374}
375
376RegisterID* ArrayNode::emitCode(CodeGenerator& generator, RegisterID* dst)
377{
378 // FIXME: Should we put all of this code into emitNewArray?
379
380 unsigned length = 0;
381 ElementNode* firstPutElement;
382 for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) {
383 if (firstPutElement->elision())
384 break;
385 ++length;
386 }
387
388 if (!firstPutElement && !m_elision)
389 return generator.emitNewArray(generator.finalDestination(dst), m_element.get());
390
391 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get());
392
393 for (ElementNode* n = firstPutElement; n; n = n->next()) {
394 RegisterID* value = generator.emitNode(n->value());
395 length += n->elision();
396 generator.emitPutByIndex(array.get(), length++, value);
397 }
398
399 if (m_elision) {
400 RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
401 generator.emitPutById(array.get(), generator.propertyNames().length, value);
402 }
403
404 return generator.moveToDestinationIfNeeded(dst, array.get());
405}
406
407// ------------------------------ PropertyNode ----------------------------
408
409PropertyNode::~PropertyNode()
410{
411 NodeReleaser::releaseAllNodes(this);
412}
413
414void PropertyNode::releaseNodes(NodeReleaser& releaser)
415{
416 releaser.release(m_assign);
417}
418
419// ------------------------------ ObjectLiteralNode ----------------------------
420
421ObjectLiteralNode::~ObjectLiteralNode()
422{
423 NodeReleaser::releaseAllNodes(this);
424}
425
426void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser)
427{
428 releaser.release(m_list);
429}
430
431RegisterID* ObjectLiteralNode::emitCode(CodeGenerator& generator, RegisterID* dst)
432{
433 if (!m_list) {
434 if (dst == ignoredResult())
435 return 0;
436 return generator.emitNewObject(generator.finalDestination(dst));
437 }
438 return generator.emitNode(dst, m_list.get());
439}
440
441// ------------------------------ PropertyListNode -----------------------------
442
443PropertyListNode::~PropertyListNode()
444{
445 NodeReleaser::releaseAllNodes(this);
446}
447
448void PropertyListNode::releaseNodes(NodeReleaser& releaser)
449{
450 releaser.release(m_node);
451 releaser.release(m_next);
452}
453
454RegisterID* PropertyListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
455{
456 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
457
458 generator.emitNewObject(newObj.get());
459
460 for (PropertyListNode* p = this; p; p = p->m_next.get()) {
461 RegisterID* value = generator.emitNode(p->m_node->m_assign.get());
462
463 switch (p->m_node->m_type) {
464 case PropertyNode::Constant: {
465 generator.emitPutById(newObj.get(), p->m_node->name(), value);
466 break;
467 }
468 case PropertyNode::Getter: {
469 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
470 break;
471 }
472 case PropertyNode::Setter: {
473 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
474 break;
475 }
476 default:
477 ASSERT_NOT_REACHED();
478 }
479 }
480
481 return generator.moveToDestinationIfNeeded(dst, newObj.get());
482}
483
484// ------------------------------ BracketAccessorNode --------------------------------
485
486BracketAccessorNode::~BracketAccessorNode()
487{
488 NodeReleaser::releaseAllNodes(this);
489}
490
491void BracketAccessorNode::releaseNodes(NodeReleaser& releaser)
492{
493 releaser.release(m_base);
494 releaser.release(m_subscript);
495}
496
497RegisterID* BracketAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
498{
499 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator));
500 RegisterID* property = generator.emitNode(m_subscript.get());
501 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
502 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
503}
504
505// ------------------------------ DotAccessorNode --------------------------------
506
507DotAccessorNode::~DotAccessorNode()
508{
509 NodeReleaser::releaseAllNodes(this);
510}
511
512void DotAccessorNode::releaseNodes(NodeReleaser& releaser)
513{
514 releaser.release(m_base);
515}
516
517RegisterID* DotAccessorNode::emitCode(CodeGenerator& generator, RegisterID* dst)
518{
519 RegisterID* base = generator.emitNode(m_base.get());
520 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
521 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
522}
523
524// ------------------------------ ArgumentListNode -----------------------------
525
526ArgumentListNode::~ArgumentListNode()
527{
528 NodeReleaser::releaseAllNodes(this);
529}
530
531void ArgumentListNode::releaseNodes(NodeReleaser& releaser)
532{
533 releaser.release(m_next);
534 releaser.release(m_expr);
535}
536
537RegisterID* ArgumentListNode::emitCode(CodeGenerator& generator, RegisterID* dst)
538{
539 ASSERT(m_expr);
540 return generator.emitNode(dst, m_expr.get());
541}
542
543// ------------------------------ ArgumentsNode -----------------------------
544
545ArgumentsNode::~ArgumentsNode()
546{
547 NodeReleaser::releaseAllNodes(this);
548}
549
550void ArgumentsNode::releaseNodes(NodeReleaser& releaser)
551{
552 releaser.release(m_listNode);
553}
554
555// ------------------------------ NewExprNode ----------------------------------
556
557NewExprNode::~NewExprNode()
558{
559 NodeReleaser::releaseAllNodes(this);
560}
561
562void NewExprNode::releaseNodes(NodeReleaser& releaser)
563{
564 releaser.release(m_expr);
565 releaser.release(m_args);
566}
567
568RegisterID* NewExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
569{
570 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
571 return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), divot(), startOffset(), endOffset());
572}
573
574// ------------------------------ EvalFunctionCallNode ----------------------------------
575
576EvalFunctionCallNode::~EvalFunctionCallNode()
577{
578 NodeReleaser::releaseAllNodes(this);
579}
580
581void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser)
582{
583 releaser.release(m_args);
584}
585
586RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
587{
588 RefPtr<RegisterID> func = generator.tempDestination(dst);
589 RefPtr<RegisterID> thisRegister = generator.newTemporary();
590 generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
591 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
592}
593
594// ------------------------------ FunctionCallValueNode ----------------------------------
595
596FunctionCallValueNode::~FunctionCallValueNode()
597{
598 NodeReleaser::releaseAllNodes(this);
599}
600
601void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser)
602{
603 releaser.release(m_expr);
604 releaser.release(m_args);
605}
606
607RegisterID* FunctionCallValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
608{
609 RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
610 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
611 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
612}
613
614// ------------------------------ FunctionCallResolveNode ----------------------------------
615
616FunctionCallResolveNode::~FunctionCallResolveNode()
617{
618 NodeReleaser::releaseAllNodes(this);
619}
620
621void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser)
622{
623 releaser.release(m_args);
624}
625
626RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
627{
628 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
629 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
630 return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
631 }
632
633 int index = 0;
634 size_t depth = 0;
635 JSObject* globalObject = 0;
636 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
637 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
638 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
639 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
640 }
641
642 RefPtr<RegisterID> func = generator.tempDestination(dst);
643 RefPtr<RegisterID> thisRegister = generator.newTemporary();
644 int identifierStart = divot() - startOffset();
645 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
646 generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident);
647 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
648}
649
650// ------------------------------ FunctionCallBracketNode ----------------------------------
651
652FunctionCallBracketNode::~FunctionCallBracketNode()
653{
654 NodeReleaser::releaseAllNodes(this);
655}
656
657void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser)
658{
659 releaser.release(m_base);
660 releaser.release(m_subscript);
661 releaser.release(m_args);
662}
663
664RegisterID* FunctionCallBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
665{
666 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
667 RegisterID* property = generator.emitNode(m_subscript.get());
668 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
669 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
670 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
671 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
672}
673
674// ------------------------------ FunctionCallDotNode ----------------------------------
675
676FunctionCallDotNode::~FunctionCallDotNode()
677{
678 NodeReleaser::releaseAllNodes(this);
679}
680
681void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser)
682{
683 releaser.release(m_base);
684 releaser.release(m_args);
685}
686
687RegisterID* FunctionCallDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
688{
689 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
690 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
691 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
692 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
693 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
694}
695
696// ------------------------------ PostfixResolveNode ----------------------------------
697
698static RegisterID* emitPreIncOrDec(CodeGenerator& generator, RegisterID* srcDst, Operator oper)
699{
700 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
701}
702
703static RegisterID* emitPostIncOrDec(CodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
704{
705 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
706}
707
708RegisterID* PostfixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
709{
710 if (RegisterID* local = generator.registerFor(m_ident)) {
711 if (generator.isLocalConstant(m_ident)) {
712 if (dst == ignoredResult())
713 return 0;
714 return generator.emitToJSNumber(generator.finalDestination(dst), local);
715 }
716
717 if (dst == ignoredResult())
718 return emitPreIncOrDec(generator, local, m_operator);
719 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
720 }
721
722 int index = 0;
723 size_t depth = 0;
724 JSObject* globalObject = 0;
725 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
726 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
727 RegisterID* oldValue;
728 if (dst == ignoredResult()) {
729 oldValue = 0;
730 emitPreIncOrDec(generator, value.get(), m_operator);
731 } else {
732 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
733 }
734 generator.emitPutScopedVar(depth, index, value.get(), globalObject);
735 return oldValue;
736 }
737
738 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
739 RefPtr<RegisterID> value = generator.newTemporary();
740 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
741 RegisterID* oldValue;
742 if (dst == ignoredResult()) {
743 oldValue = 0;
744 emitPreIncOrDec(generator, value.get(), m_operator);
745 } else {
746 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
747 }
748 generator.emitPutById(base.get(), m_ident, value.get());
749 return oldValue;
750}
751
752// ------------------------------ PostfixBracketNode ----------------------------------
753
754PostfixBracketNode::~PostfixBracketNode()
755{
756 NodeReleaser::releaseAllNodes(this);
757}
758
759void PostfixBracketNode::releaseNodes(NodeReleaser& releaser)
760{
761 releaser.release(m_base);
762 releaser.release(m_subscript);
763}
764
765RegisterID* PostfixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
766{
767 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
768 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
769
770 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
771 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
772 RegisterID* oldValue;
773 if (dst == ignoredResult()) {
774 oldValue = 0;
775 if (m_operator == OpPlusPlus)
776 generator.emitPreInc(value.get());
777 else
778 generator.emitPreDec(value.get());
779 } else {
780 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
781 }
782 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
783 generator.emitPutByVal(base.get(), property.get(), value.get());
784 return oldValue;
785}
786
787// ------------------------------ PostfixDotNode ----------------------------------
788
789PostfixDotNode::~PostfixDotNode()
790{
791 NodeReleaser::releaseAllNodes(this);
792}
793
794void PostfixDotNode::releaseNodes(NodeReleaser& releaser)
795{
796 releaser.release(m_base);
797}
798
799RegisterID* PostfixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
800{
801 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
802
803 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
804 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
805 RegisterID* oldValue;
806 if (dst == ignoredResult()) {
807 oldValue = 0;
808 if (m_operator == OpPlusPlus)
809 generator.emitPreInc(value.get());
810 else
811 generator.emitPreDec(value.get());
812 } else {
813 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
814 }
815 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
816 generator.emitPutById(base.get(), m_ident, value.get());
817 return oldValue;
818}
819
820// ------------------------------ PostfixErrorNode -----------------------------------
821
822PostfixErrorNode::~PostfixErrorNode()
823{
824 NodeReleaser::releaseAllNodes(this);
825}
826
827void PostfixErrorNode::releaseNodes(NodeReleaser& releaser)
828{
829 releaser.release(m_expr);
830}
831
832RegisterID* PostfixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
833{
834 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.");
835}
836
837// ------------------------------ DeleteResolveNode -----------------------------------
838
839RegisterID* DeleteResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
840{
841 if (generator.registerFor(m_ident))
842 return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
843
844 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
845 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
846 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
847}
848
849// ------------------------------ DeleteBracketNode -----------------------------------
850
851DeleteBracketNode::~DeleteBracketNode()
852{
853 NodeReleaser::releaseAllNodes(this);
854}
855
856void DeleteBracketNode::releaseNodes(NodeReleaser& releaser)
857{
858 releaser.release(m_base);
859 releaser.release(m_subscript);
860}
861
862RegisterID* DeleteBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
863{
864 RefPtr<RegisterID> r0 = generator.emitNode(m_base.get());
865 RegisterID* r1 = generator.emitNode(m_subscript.get());
866
867 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
868 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
869}
870
871// ------------------------------ DeleteDotNode -----------------------------------
872
873DeleteDotNode::~DeleteDotNode()
874{
875 NodeReleaser::releaseAllNodes(this);
876}
877
878void DeleteDotNode::releaseNodes(NodeReleaser& releaser)
879{
880 releaser.release(m_base);
881}
882
883RegisterID* DeleteDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
884{
885 RegisterID* r0 = generator.emitNode(m_base.get());
886
887 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
888 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
889}
890
891// ------------------------------ DeleteValueNode -----------------------------------
892
893DeleteValueNode::~DeleteValueNode()
894{
895 NodeReleaser::releaseAllNodes(this);
896}
897
898void DeleteValueNode::releaseNodes(NodeReleaser& releaser)
899{
900 releaser.release(m_expr);
901}
902
903RegisterID* DeleteValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
904{
905 generator.emitNode(ignoredResult(), m_expr.get());
906
907 // delete on a non-location expression ignores the value and returns true
908 return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
909}
910
911// ------------------------------ VoidNode -------------------------------------
912
913VoidNode::~VoidNode()
914{
915 NodeReleaser::releaseAllNodes(this);
916}
917
918void VoidNode::releaseNodes(NodeReleaser& releaser)
919{
920 releaser.release(m_expr);
921}
922
923RegisterID* VoidNode::emitCode(CodeGenerator& generator, RegisterID* dst)
924{
925 if (dst == ignoredResult()) {
926 generator.emitNode(ignoredResult(), m_expr.get());
927 return 0;
928 }
929 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
930 return generator.emitLoad(dst, jsUndefined());
931}
932
933// ------------------------------ TypeOfValueNode -----------------------------------
934
935RegisterID* TypeOfResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
936{
937 if (RegisterID* local = generator.registerFor(m_ident)) {
938 if (dst == ignoredResult())
939 return 0;
940 return generator.emitTypeOf(generator.finalDestination(dst), local);
941 }
942
943 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
944 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
945 if (dst == ignoredResult())
946 return 0;
947 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
948}
949
950// ------------------------------ TypeOfValueNode -----------------------------------
951
952TypeOfValueNode::~TypeOfValueNode()
953{
954 NodeReleaser::releaseAllNodes(this);
955}
956
957void TypeOfValueNode::releaseNodes(NodeReleaser& releaser)
958{
959 releaser.release(m_expr);
960}
961
962RegisterID* TypeOfValueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
963{
964 if (dst == ignoredResult()) {
965 generator.emitNode(ignoredResult(), m_expr.get());
966 return 0;
967 }
968 RefPtr<RegisterID> src = generator.emitNode(m_expr.get());
969 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
970}
971
972// ------------------------------ PrefixResolveNode ----------------------------------
973
974RegisterID* PrefixResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
975{
976 if (RegisterID* local = generator.registerFor(m_ident)) {
977 if (generator.isLocalConstant(m_ident)) {
978 if (dst == ignoredResult())
979 return 0;
980 RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
981 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
982 }
983
984 emitPreIncOrDec(generator, local, m_operator);
985 return generator.moveToDestinationIfNeeded(dst, local);
986 }
987
988 int index = 0;
989 size_t depth = 0;
990 JSObject* globalObject = 0;
991 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
992 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
993 emitPreIncOrDec(generator, propDst.get(), m_operator);
994 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
995 return generator.moveToDestinationIfNeeded(dst, propDst.get());
996 }
997
998 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
999 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1000 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
1001 emitPreIncOrDec(generator, propDst.get(), m_operator);
1002 generator.emitPutById(base.get(), m_ident, propDst.get());
1003 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1004}
1005
1006// ------------------------------ PrefixBracketNode ----------------------------------
1007
1008PrefixBracketNode::~PrefixBracketNode()
1009{
1010 NodeReleaser::releaseAllNodes(this);
1011}
1012
1013void PrefixBracketNode::releaseNodes(NodeReleaser& releaser)
1014{
1015 releaser.release(m_base);
1016 releaser.release(m_subscript);
1017}
1018
1019RegisterID* PrefixBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1020{
1021 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1022 RefPtr<RegisterID> property = generator.emitNode(m_subscript.get());
1023 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1024
1025 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
1026 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
1027 if (m_operator == OpPlusPlus)
1028 generator.emitPreInc(value);
1029 else
1030 generator.emitPreDec(value);
1031 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1032 generator.emitPutByVal(base.get(), property.get(), value);
1033 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1034}
1035
1036// ------------------------------ PrefixDotNode ----------------------------------
1037
1038PrefixDotNode::~PrefixDotNode()
1039{
1040 NodeReleaser::releaseAllNodes(this);
1041}
1042
1043void PrefixDotNode::releaseNodes(NodeReleaser& releaser)
1044{
1045 releaser.release(m_base);
1046}
1047
1048RegisterID* PrefixDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1049{
1050 RefPtr<RegisterID> base = generator.emitNode(m_base.get());
1051 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1052
1053 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
1054 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
1055 if (m_operator == OpPlusPlus)
1056 generator.emitPreInc(value);
1057 else
1058 generator.emitPreDec(value);
1059 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1060 generator.emitPutById(base.get(), m_ident, value);
1061 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1062}
1063
1064// ------------------------------ PrefixErrorNode -----------------------------------
1065
1066PrefixErrorNode::~PrefixErrorNode()
1067{
1068 NodeReleaser::releaseAllNodes(this);
1069}
1070
1071void PrefixErrorNode::releaseNodes(NodeReleaser& releaser)
1072{
1073 releaser.release(m_expr);
1074}
1075
1076RegisterID* PrefixErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
1077{
1078 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.");
1079}
1080
1081// ------------------------------ Unary Operation Nodes -----------------------------------
1082
1083UnaryOpNode::~UnaryOpNode()
1084{
1085 NodeReleaser::releaseAllNodes(this);
1086}
1087
1088void UnaryOpNode::releaseNodes(NodeReleaser& releaser)
1089{
1090 releaser.release(m_expr);
1091}
1092
1093RegisterID* UnaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1094{
1095 RegisterID* src = generator.emitNode(m_expr.get());
1096 return generator.emitUnaryOp(opcode(), generator.finalDestination(dst), src, m_expr->resultDescriptor());
1097}
1098
1099// ------------------------------ Binary Operation Nodes -----------------------------------
1100
1101BinaryOpNode::~BinaryOpNode()
1102{
1103 NodeReleaser::releaseAllNodes(this);
1104}
1105
1106void BinaryOpNode::releaseNodes(NodeReleaser& releaser)
1107{
1108 releaser.release(m_expr1);
1109 releaser.release(m_expr2);
1110}
1111
1112RegisterID* BinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1113{
1114 OpcodeID opcode = this->opcode();
1115 if (opcode == op_neq) {
1116 if (m_expr1->isNull() || m_expr2->isNull()) {
1117 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
1118 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
1119 }
1120 }
1121
1122 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1123 RegisterID* src2 = generator.emitNode(m_expr2.get());
1124 return generator.emitBinaryOp(opcode, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1125}
1126
1127RegisterID* EqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1128{
1129 if (m_expr1->isNull() || m_expr2->isNull()) {
1130 RefPtr<RegisterID> src = generator.emitNode(dst, m_expr1->isNull() ? m_expr2.get() : m_expr1.get());
1131 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get(), ResultType::unknown());
1132 }
1133
1134 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1135 RegisterID* src2 = generator.emitNode(m_expr2.get());
1136 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1137}
1138
1139RegisterID* StrictEqualNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1140{
1141 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1142 RegisterID* src2 = generator.emitNode(m_expr2.get());
1143 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1144}
1145
1146RegisterID* ReverseBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1147{
1148 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1149 RegisterID* src2 = generator.emitNode(m_expr2.get());
1150 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
1151}
1152
1153RegisterID* ThrowableBinaryOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1154{
1155 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1156 RegisterID* src2 = generator.emitNode(m_expr2.get());
1157 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1158 return generator.emitBinaryOp(opcode(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1159}
1160
1161RegisterID* InstanceOfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1162{
1163 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator));
1164 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get());
1165
1166 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1167 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
1168
1169 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1170 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
1171}
1172
1173// ------------------------------ LogicalOpNode ----------------------------
1174
1175LogicalOpNode::~LogicalOpNode()
1176{
1177 NodeReleaser::releaseAllNodes(this);
1178}
1179
1180void LogicalOpNode::releaseNodes(NodeReleaser& releaser)
1181{
1182 releaser.release(m_expr1);
1183 releaser.release(m_expr2);
1184}
1185
1186RegisterID* LogicalOpNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1187{
1188 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1189 RefPtr<LabelID> target = generator.newLabel();
1190
1191 generator.emitNode(temp.get(), m_expr1.get());
1192 if (m_operator == OpLogicalAnd)
1193 generator.emitJumpIfFalse(temp.get(), target.get());
1194 else
1195 generator.emitJumpIfTrue(temp.get(), target.get());
1196 generator.emitNode(temp.get(), m_expr2.get());
1197 generator.emitLabel(target.get());
1198
1199 return generator.moveToDestinationIfNeeded(dst, temp.get());
1200}
1201
1202// ------------------------------ ConditionalNode ------------------------------
1203
1204ConditionalNode::~ConditionalNode()
1205{
1206 NodeReleaser::releaseAllNodes(this);
1207}
1208
1209void ConditionalNode::releaseNodes(NodeReleaser& releaser)
1210{
1211 releaser.release(m_logical);
1212 releaser.release(m_expr1);
1213 releaser.release(m_expr2);
1214}
1215
1216RegisterID* ConditionalNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1217{
1218 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1219 RefPtr<LabelID> beforeElse = generator.newLabel();
1220 RefPtr<LabelID> afterElse = generator.newLabel();
1221
1222 RegisterID* cond = generator.emitNode(m_logical.get());
1223 generator.emitJumpIfFalse(cond, beforeElse.get());
1224
1225 generator.emitNode(newDst.get(), m_expr1.get());
1226 generator.emitJump(afterElse.get());
1227
1228 generator.emitLabel(beforeElse.get());
1229 generator.emitNode(newDst.get(), m_expr2.get());
1230
1231 generator.emitLabel(afterElse.get());
1232
1233 return newDst.get();
1234}
1235
1236// ------------------------------ ReadModifyResolveNode -----------------------------------
1237
1238ReadModifyResolveNode::~ReadModifyResolveNode()
1239{
1240 NodeReleaser::releaseAllNodes(this);
1241}
1242
1243void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser)
1244{
1245 releaser.release(m_right);
1246}
1247
1248// FIXME: should this be moved to be a method on CodeGenerator?
1249static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(CodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types)
1250{
1251 OpcodeID opcode;
1252 switch (oper) {
1253 case OpMultEq:
1254 opcode = op_mul;
1255 break;
1256 case OpDivEq:
1257 opcode = op_div;
1258 break;
1259 case OpPlusEq:
1260 opcode = op_add;
1261 break;
1262 case OpMinusEq:
1263 opcode = op_sub;
1264 break;
1265 case OpLShift:
1266 opcode = op_lshift;
1267 break;
1268 case OpRShift:
1269 opcode = op_rshift;
1270 break;
1271 case OpURShift:
1272 opcode = op_urshift;
1273 break;
1274 case OpAndEq:
1275 opcode = op_bitand;
1276 break;
1277 case OpXOrEq:
1278 opcode = op_bitxor;
1279 break;
1280 case OpOrEq:
1281 opcode = op_bitor;
1282 break;
1283 case OpModEq:
1284 opcode = op_mod;
1285 break;
1286 default:
1287 ASSERT_NOT_REACHED();
1288 return dst;
1289 }
1290
1291 return generator.emitBinaryOp(opcode, dst, src1, src2, types);
1292}
1293
1294RegisterID* ReadModifyResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1295{
1296 if (RegisterID* local = generator.registerFor(m_ident)) {
1297 if (generator.isLocalConstant(m_ident)) {
1298 RegisterID* src2 = generator.emitNode(m_right.get());
1299 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1300 }
1301
1302 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1303 RefPtr<RegisterID> result = generator.newTemporary();
1304 generator.emitMove(result.get(), local);
1305 RegisterID* src2 = generator.emitNode(m_right.get());
1306 emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1307 generator.emitMove(local, result.get());
1308 return generator.moveToDestinationIfNeeded(dst, result.get());
1309 }
1310
1311 RegisterID* src2 = generator.emitNode(m_right.get());
1312 RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1313 return generator.moveToDestinationIfNeeded(dst, result);
1314 }
1315
1316 int index = 0;
1317 size_t depth = 0;
1318 JSObject* globalObject = 0;
1319 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1320 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
1321 RegisterID* src2 = generator.emitNode(m_right.get());
1322 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1323 generator.emitPutScopedVar(depth, index, result, globalObject);
1324 return result;
1325 }
1326
1327 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
1328 generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
1329 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
1330 RegisterID* src2 = generator.emitNode(m_right.get());
1331 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1332 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1333 return generator.emitPutById(base.get(), m_ident, result);
1334}
1335
1336// ------------------------------ AssignResolveNode -----------------------------------
1337
1338AssignResolveNode::~AssignResolveNode()
1339{
1340 NodeReleaser::releaseAllNodes(this);
1341}
1342
1343void AssignResolveNode::releaseNodes(NodeReleaser& releaser)
1344{
1345 releaser.release(m_right);
1346}
1347
1348RegisterID* AssignResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1349{
1350 if (RegisterID* local = generator.registerFor(m_ident)) {
1351 if (generator.isLocalConstant(m_ident))
1352 return generator.emitNode(dst, m_right.get());
1353
1354 RegisterID* result = generator.emitNode(local, m_right.get());
1355 return generator.moveToDestinationIfNeeded(dst, result);
1356 }
1357
1358 int index = 0;
1359 size_t depth = 0;
1360 JSObject* globalObject = 0;
1361 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1362 if (dst == ignoredResult())
1363 dst = 0;
1364 RegisterID* value = generator.emitNode(dst, m_right.get());
1365 generator.emitPutScopedVar(depth, index, value, globalObject);
1366 return value;
1367 }
1368
1369 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1370 if (dst == ignoredResult())
1371 dst = 0;
1372 RegisterID* value = generator.emitNode(dst, m_right.get());
1373 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1374 return generator.emitPutById(base.get(), m_ident, value);
1375}
1376
1377// ------------------------------ AssignDotNode -----------------------------------
1378
1379AssignDotNode::~AssignDotNode()
1380{
1381 NodeReleaser::releaseAllNodes(this);
1382}
1383
1384void AssignDotNode::releaseNodes(NodeReleaser& releaser)
1385{
1386 releaser.release(m_base);
1387 releaser.release(m_right);
1388}
1389
1390RegisterID* AssignDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1391{
1392 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
1393 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1394 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1395 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1396 generator.emitPutById(base.get(), m_ident, result);
1397 return generator.moveToDestinationIfNeeded(dst, result);
1398}
1399
1400// ------------------------------ ReadModifyDotNode -----------------------------------
1401
1402ReadModifyDotNode::~ReadModifyDotNode()
1403{
1404 NodeReleaser::releaseAllNodes(this);
1405}
1406
1407void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser)
1408{
1409 releaser.release(m_base);
1410 releaser.release(m_right);
1411}
1412
1413RegisterID* ReadModifyDotNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1414{
1415 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator));
1416
1417 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1418 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1419 RegisterID* change = generator.emitNode(m_right.get());
1420 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1421
1422 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1423 return generator.emitPutById(base.get(), m_ident, updatedValue);
1424}
1425
1426// ------------------------------ AssignErrorNode -----------------------------------
1427
1428AssignErrorNode::~AssignErrorNode()
1429{
1430 NodeReleaser::releaseAllNodes(this);
1431}
1432
1433void AssignErrorNode::releaseNodes(NodeReleaser& releaser)
1434{
1435 releaser.release(m_left);
1436 releaser.release(m_right);
1437}
1438
1439RegisterID* AssignErrorNode::emitCode(CodeGenerator& generator, RegisterID*)
1440{
1441 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
1442}
1443
1444// ------------------------------ AssignBracketNode -----------------------------------
1445
1446AssignBracketNode::~AssignBracketNode()
1447{
1448 NodeReleaser::releaseAllNodes(this);
1449}
1450
1451void AssignBracketNode::releaseNodes(NodeReleaser& releaser)
1452{
1453 releaser.release(m_base);
1454 releaser.release(m_subscript);
1455 releaser.release(m_right);
1456}
1457
1458RegisterID* AssignBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1459{
1460 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1461 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1462 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1463 RegisterID* result = generator.emitNode(value.get(), m_right.get());
1464
1465 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1466 generator.emitPutByVal(base.get(), property.get(), result);
1467 return generator.moveToDestinationIfNeeded(dst, result);
1468}
1469
1470// ------------------------------ ReadModifyBracketNode -----------------------------------
1471
1472ReadModifyBracketNode::~ReadModifyBracketNode()
1473{
1474 NodeReleaser::releaseAllNodes(this);
1475}
1476
1477void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser)
1478{
1479 releaser.release(m_base);
1480 releaser.release(m_subscript);
1481 releaser.release(m_right);
1482}
1483
1484RegisterID* ReadModifyBracketNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1485{
1486 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1487 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator));
1488
1489 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1490 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1491 RegisterID* change = generator.emitNode(m_right.get());
1492 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknown(), m_right->resultDescriptor()));
1493
1494 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1495 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1496
1497 return updatedValue;
1498}
1499
1500// ------------------------------ CommaNode ------------------------------------
1501
1502CommaNode::~CommaNode()
1503{
1504 NodeReleaser::releaseAllNodes(this);
1505}
1506
1507void CommaNode::releaseNodes(NodeReleaser& releaser)
1508{
1509 releaser.release(m_expr1);
1510 releaser.release(m_expr2);
1511}
1512
1513RegisterID* CommaNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1514{
1515 generator.emitNode(ignoredResult(), m_expr1.get());
1516 return generator.emitNode(dst, m_expr2.get());
1517}
1518
1519// ------------------------------ ConstDeclNode ------------------------------------
1520
1521ConstDeclNode::~ConstDeclNode()
1522{
1523 NodeReleaser::releaseAllNodes(this);
1524}
1525
1526void ConstDeclNode::releaseNodes(NodeReleaser& releaser)
1527{
1528 releaser.release(m_next);
1529 releaser.release(m_init);
1530}
1531
1532ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init)
1533 : ExpressionNode(globalData)
1534 , m_ident(ident)
1535 , m_init(init)
1536{
1537}
1538
1539RegisterID* ConstDeclNode::emitCodeSingle(CodeGenerator& generator)
1540{
1541 if (RegisterID* local = generator.constRegisterFor(m_ident)) {
1542 if (!m_init)
1543 return local;
1544
1545 return generator.emitNode(local, m_init.get());
1546 }
1547
1548 // FIXME: While this code should only be hit in eval code, it will potentially
1549 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1550 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1551 RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined());
1552 return generator.emitPutById(base.get(), m_ident, value);
1553}
1554
1555RegisterID* ConstDeclNode::emitCode(CodeGenerator& generator, RegisterID*)
1556{
1557 RegisterID* result = 0;
1558 for (ConstDeclNode* n = this; n; n = n->m_next.get())
1559 result = n->emitCodeSingle(generator);
1560
1561 return result;
1562}
1563
1564// ------------------------------ ConstStatementNode -----------------------------
1565
1566ConstStatementNode::~ConstStatementNode()
1567{
1568 NodeReleaser::releaseAllNodes(this);
1569}
1570
1571void ConstStatementNode::releaseNodes(NodeReleaser& releaser)
1572{
1573 releaser.release(m_next);
1574}
1575
1576RegisterID* ConstStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1577{
1578 return generator.emitNode(m_next.get());
1579}
1580
1581// ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
1582
1583static inline RegisterID* statementListEmitCode(const StatementVector& statements, CodeGenerator& generator, RegisterID* dst)
1584{
1585 StatementVector::const_iterator end = statements.end();
1586 for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) {
1587 StatementNode* n = it->get();
1588 if (!n->isLoop())
1589 generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine());
1590 generator.emitNode(dst, n);
1591 }
1592 return 0;
1593}
1594
1595// ------------------------------ BlockNode ------------------------------------
1596
1597BlockNode::~BlockNode()
1598{
1599 NodeReleaser::releaseAllNodes(this);
1600}
1601
1602void BlockNode::releaseNodes(NodeReleaser& releaser)
1603{
1604 size_t size = m_children.size();
1605 for (size_t i = 0; i < size; ++i)
1606 releaser.release(m_children[i]);
1607}
1608
1609BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children)
1610 : StatementNode(globalData)
1611{
1612 if (children)
1613 children->releaseContentsIntoVector(m_children);
1614}
1615
1616RegisterID* BlockNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1617{
1618 return statementListEmitCode(m_children, generator, dst);
1619}
1620
1621// ------------------------------ EmptyStatementNode ---------------------------
1622
1623RegisterID* EmptyStatementNode::emitCode(CodeGenerator&, RegisterID* dst)
1624{
1625 return dst;
1626}
1627
1628// ------------------------------ DebuggerStatementNode ---------------------------
1629
1630RegisterID* DebuggerStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1631{
1632 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1633 return dst;
1634}
1635
1636// ------------------------------ ExprStatementNode ----------------------------
1637
1638RegisterID* ExprStatementNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1639{
1640 ASSERT(m_expr);
1641 return generator.emitNode(dst, m_expr.get());
1642}
1643
1644// ------------------------------ VarStatementNode ----------------------------
1645
1646VarStatementNode::~VarStatementNode()
1647{
1648 NodeReleaser::releaseAllNodes(this);
1649}
1650
1651void VarStatementNode::releaseNodes(NodeReleaser& releaser)
1652{
1653 releaser.release(m_expr);
1654}
1655
1656RegisterID* VarStatementNode::emitCode(CodeGenerator& generator, RegisterID*)
1657{
1658 ASSERT(m_expr);
1659 return generator.emitNode(m_expr.get());
1660}
1661
1662// ------------------------------ IfNode ---------------------------------------
1663
1664IfNode::~IfNode()
1665{
1666 NodeReleaser::releaseAllNodes(this);
1667}
1668
1669void IfNode::releaseNodes(NodeReleaser& releaser)
1670{
1671 releaser.release(m_condition);
1672 releaser.release(m_ifBlock);
1673}
1674
1675RegisterID* IfNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1676{
1677 RefPtr<LabelID> afterThen = generator.newLabel();
1678
1679 RegisterID* cond = generator.emitNode(m_condition.get());
1680 generator.emitJumpIfFalse(cond, afterThen.get());
1681
1682 if (!m_ifBlock->isBlock())
1683 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1684
1685 generator.emitNode(dst, m_ifBlock.get());
1686 generator.emitLabel(afterThen.get());
1687
1688 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1689 return 0;
1690}
1691
1692// ------------------------------ IfElseNode ---------------------------------------
1693
1694IfElseNode::~IfElseNode()
1695{
1696 NodeReleaser::releaseAllNodes(this);
1697}
1698
1699void IfElseNode::releaseNodes(NodeReleaser& releaser)
1700{
1701 releaser.release(m_elseBlock);
1702 IfNode::releaseNodes(releaser);
1703}
1704
1705RegisterID* IfElseNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1706{
1707 RefPtr<LabelID> beforeElse = generator.newLabel();
1708 RefPtr<LabelID> afterElse = generator.newLabel();
1709
1710 RegisterID* cond = generator.emitNode(m_condition.get());
1711 generator.emitJumpIfFalse(cond, beforeElse.get());
1712
1713 if (!m_ifBlock->isBlock())
1714 generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine());
1715
1716 generator.emitNode(dst, m_ifBlock.get());
1717 generator.emitJump(afterElse.get());
1718
1719 generator.emitLabel(beforeElse.get());
1720
1721 if (!m_elseBlock->isBlock())
1722 generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine());
1723
1724 generator.emitNode(dst, m_elseBlock.get());
1725
1726 generator.emitLabel(afterElse.get());
1727
1728 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1729 return 0;
1730}
1731
1732// ------------------------------ DoWhileNode ----------------------------------
1733
1734DoWhileNode::~DoWhileNode()
1735{
1736 NodeReleaser::releaseAllNodes(this);
1737}
1738
1739void DoWhileNode::releaseNodes(NodeReleaser& releaser)
1740{
1741 releaser.release(m_statement);
1742 releaser.release(m_expr);
1743}
1744
1745RegisterID* DoWhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1746{
1747 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1748
1749 RefPtr<LabelID> topOfLoop = generator.newLabel();
1750 generator.emitLabel(topOfLoop.get());
1751
1752 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1753
1754 if (!m_statement->isBlock())
1755 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1756
1757 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1758
1759 generator.emitLabel(scope->continueTarget());
1760 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1761 RegisterID* cond = generator.emitNode(m_expr.get());
1762 generator.emitJumpIfTrue(cond, topOfLoop.get());
1763
1764 generator.emitLabel(scope->breakTarget());
1765 return result.get();
1766}
1767
1768// ------------------------------ WhileNode ------------------------------------
1769
1770WhileNode::~WhileNode()
1771{
1772 NodeReleaser::releaseAllNodes(this);
1773}
1774
1775void WhileNode::releaseNodes(NodeReleaser& releaser)
1776{
1777 releaser.release(m_expr);
1778 releaser.release(m_statement);
1779}
1780
1781RegisterID* WhileNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1782{
1783 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1784
1785 generator.emitJump(scope->continueTarget());
1786
1787 RefPtr<LabelID> topOfLoop = generator.newLabel();
1788 generator.emitLabel(topOfLoop.get());
1789
1790 if (!m_statement->isBlock())
1791 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1792
1793 generator.emitNode(dst, m_statement.get());
1794
1795 generator.emitLabel(scope->continueTarget());
1796 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1797 RegisterID* cond = generator.emitNode(m_expr.get());
1798 generator.emitJumpIfTrue(cond, topOfLoop.get());
1799
1800 generator.emitLabel(scope->breakTarget());
1801
1802 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1803 return 0;
1804}
1805
1806// ------------------------------ ForNode --------------------------------------
1807
1808ForNode::~ForNode()
1809{
1810 NodeReleaser::releaseAllNodes(this);
1811}
1812
1813void ForNode::releaseNodes(NodeReleaser& releaser)
1814{
1815 releaser.release(m_expr1);
1816 releaser.release(m_expr2);
1817 releaser.release(m_expr3);
1818 releaser.release(m_statement);
1819}
1820
1821RegisterID* ForNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1822{
1823 if (dst == ignoredResult())
1824 dst = 0;
1825
1826 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1827
1828 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1829
1830 if (m_expr1)
1831 generator.emitNode(ignoredResult(), m_expr1.get());
1832
1833 RefPtr<LabelID> condition = generator.newLabel();
1834 generator.emitJump(condition.get());
1835
1836 RefPtr<LabelID> topOfLoop = generator.newLabel();
1837 generator.emitLabel(topOfLoop.get());
1838
1839 if (!m_statement->isBlock())
1840 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1841 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get());
1842
1843 generator.emitLabel(scope->continueTarget());
1844 if (m_expr3)
1845 generator.emitNode(ignoredResult(), m_expr3.get());
1846
1847 generator.emitLabel(condition.get());
1848 if (m_expr2) {
1849 RegisterID* cond = generator.emitNode(m_expr2.get());
1850 generator.emitJumpIfTrue(cond, topOfLoop.get());
1851 } else
1852 generator.emitJump(topOfLoop.get());
1853
1854 generator.emitLabel(scope->breakTarget());
1855 return result.get();
1856}
1857
1858// ------------------------------ ForInNode ------------------------------------
1859
1860ForInNode::~ForInNode()
1861{
1862 NodeReleaser::releaseAllNodes(this);
1863}
1864
1865void ForInNode::releaseNodes(NodeReleaser& releaser)
1866{
1867 releaser.release(m_init);
1868 releaser.release(m_lexpr);
1869 releaser.release(m_expr);
1870 releaser.release(m_statement);
1871}
1872
1873ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement)
1874 : StatementNode(globalData)
1875 , m_init(0L)
1876 , m_lexpr(l)
1877 , m_expr(expr)
1878 , m_statement(statement)
1879 , m_identIsVarDecl(false)
1880{
1881}
1882
1883ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset)
1884 : StatementNode(globalData)
1885 , m_ident(ident)
1886 , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset))
1887 , m_expr(expr)
1888 , m_statement(statement)
1889 , m_identIsVarDecl(true)
1890{
1891 if (in) {
1892 AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true);
1893 node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot);
1894 m_init = node;
1895 }
1896 // for( var foo = bar in baz )
1897}
1898
1899RegisterID* ForInNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1900{
1901 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1902
1903 if (!m_lexpr->isLocation())
1904 return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
1905
1906 RefPtr<LabelID> continueTarget = generator.newLabel();
1907
1908 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1909
1910 if (m_init)
1911 generator.emitNode(ignoredResult(), m_init.get());
1912 RegisterID* forInBase = generator.emitNode(m_expr.get());
1913 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1914 generator.emitJump(scope->continueTarget());
1915
1916 RefPtr<LabelID> loopStart = generator.newLabel();
1917 generator.emitLabel(loopStart.get());
1918
1919 RegisterID* propertyName;
1920 if (m_lexpr->isResolveNode()) {
1921 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier();
1922 propertyName = generator.registerFor(ident);
1923 if (!propertyName) {
1924 propertyName = generator.newTemporary();
1925 RefPtr<RegisterID> protect = propertyName;
1926 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1927
1928 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1929 generator.emitPutById(base, ident, propertyName);
1930 }
1931 } else if (m_lexpr->isDotAccessorNode()) {
1932 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get());
1933 const Identifier& ident = assignNode->identifier();
1934 propertyName = generator.newTemporary();
1935 RefPtr<RegisterID> protect = propertyName;
1936 RegisterID* base = generator.emitNode(assignNode->base());
1937
1938 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1939 generator.emitPutById(base, ident, propertyName);
1940 } else {
1941 ASSERT(m_lexpr->isBracketAccessorNode());
1942 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get());
1943 propertyName = generator.newTemporary();
1944 RefPtr<RegisterID> protect = propertyName;
1945 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1946 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1947
1948 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1949 generator.emitPutByVal(base.get(), subscript, propertyName);
1950 }
1951
1952 if (!m_statement->isBlock())
1953 generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine());
1954 generator.emitNode(dst, m_statement.get());
1955
1956 generator.emitLabel(scope->continueTarget());
1957 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1958 generator.emitLabel(scope->breakTarget());
1959 return dst;
1960}
1961
1962// ------------------------------ ContinueNode ---------------------------------
1963
1964// ECMA 12.7
1965RegisterID* ContinueNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1966{
1967 LabelScope* scope = generator.continueTarget(m_ident);
1968
1969 if (!scope)
1970 return m_ident.isEmpty()
1971 ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
1972 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1973
1974 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
1975 return dst;
1976}
1977
1978// ------------------------------ BreakNode ------------------------------------
1979
1980// ECMA 12.8
1981RegisterID* BreakNode::emitCode(CodeGenerator& generator, RegisterID* dst)
1982{
1983 LabelScope* scope = generator.breakTarget(m_ident);
1984
1985 if (!scope)
1986 return m_ident.isEmpty()
1987 ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
1988 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1989
1990 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
1991 return dst;
1992}
1993
1994// ------------------------------ ReturnNode -----------------------------------
1995
1996ReturnNode::~ReturnNode()
1997{
1998 NodeReleaser::releaseAllNodes(this);
1999}
2000
2001void ReturnNode::releaseNodes(NodeReleaser& releaser)
2002{
2003 releaser.release(m_value);
2004}
2005
2006RegisterID* ReturnNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2007{
2008 if (generator.codeType() != FunctionCode)
2009 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
2010
2011 if (dst == ignoredResult())
2012 dst = 0;
2013 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined());
2014 if (generator.scopeDepth()) {
2015 RefPtr<LabelID> l0 = generator.newLabel();
2016 generator.emitJumpScopes(l0.get(), 0);
2017 generator.emitLabel(l0.get());
2018 }
2019 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2020 return generator.emitReturn(r0);
2021}
2022
2023// ------------------------------ WithNode -------------------------------------
2024
2025WithNode::~WithNode()
2026{
2027 NodeReleaser::releaseAllNodes(this);
2028}
2029
2030void WithNode::releaseNodes(NodeReleaser& releaser)
2031{
2032 releaser.release(m_expr);
2033 releaser.release(m_statement);
2034}
2035
2036RegisterID* WithNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2037{
2038 RefPtr<RegisterID> scope = generator.emitNode(m_expr.get()); // scope must be protected until popped
2039 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
2040 generator.emitPushScope(scope.get());
2041 RegisterID* result = generator.emitNode(dst, m_statement.get());
2042 generator.emitPopScope();
2043 return result;
2044}
2045
2046// ------------------------------ CaseClauseNode --------------------------------
2047
2048CaseClauseNode::~CaseClauseNode()
2049{
2050 NodeReleaser::releaseAllNodes(this);
2051}
2052
2053void CaseClauseNode::releaseNodes(NodeReleaser& releaser)
2054{
2055 releaser.release(m_expr);
2056}
2057
2058// ------------------------------ ClauseListNode --------------------------------
2059
2060ClauseListNode::~ClauseListNode()
2061{
2062 NodeReleaser::releaseAllNodes(this);
2063}
2064
2065void ClauseListNode::releaseNodes(NodeReleaser& releaser)
2066{
2067 releaser.release(m_clause);
2068 releaser.release(m_next);
2069}
2070
2071// ------------------------------ CaseBlockNode --------------------------------
2072
2073CaseBlockNode::~CaseBlockNode()
2074{
2075 NodeReleaser::releaseAllNodes(this);
2076}
2077
2078void CaseBlockNode::releaseNodes(NodeReleaser& releaser)
2079{
2080 releaser.release(m_list1);
2081 releaser.release(m_defaultClause);
2082 releaser.release(m_list2);
2083}
2084
2085enum SwitchKind {
2086 SwitchUnset = 0,
2087 SwitchNumber = 1,
2088 SwitchString = 2,
2089 SwitchNeither = 3
2090};
2091
2092static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2093{
2094 for (; list; list = list->getNext()) {
2095 ExpressionNode* clauseExpression = list->getClause()->expr();
2096 literalVector.append(clauseExpression);
2097 if (clauseExpression->isNumber()) {
2098 double value = static_cast<NumberNode*>(clauseExpression)->value();
2099 if ((typeForTable & ~SwitchNumber) || !JSImmediate::from(value)) {
2100 typeForTable = SwitchNeither;
2101 break;
2102 }
2103 int32_t intVal = static_cast<int32_t>(value);
2104 ASSERT(intVal == value);
2105 if (intVal < min_num)
2106 min_num = intVal;
2107 if (intVal > max_num)
2108 max_num = intVal;
2109 typeForTable = SwitchNumber;
2110 continue;
2111 }
2112 if (clauseExpression->isString()) {
2113 if (typeForTable & ~SwitchString) {
2114 typeForTable = SwitchNeither;
2115 break;
2116 }
2117 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
2118 if (singleCharacterSwitch &= value.size() == 1) {
2119 int32_t intVal = value.rep()->data()[0];
2120 if (intVal < min_num)
2121 min_num = intVal;
2122 if (intVal > max_num)
2123 max_num = intVal;
2124 }
2125 typeForTable = SwitchString;
2126 continue;
2127 }
2128 typeForTable = SwitchNeither;
2129 break;
2130 }
2131}
2132
2133SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2134{
2135 SwitchKind typeForTable = SwitchUnset;
2136 bool singleCharacterSwitch = true;
2137
2138 processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2139 processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2140
2141 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2142 return SwitchInfo::SwitchNone;
2143
2144 if (typeForTable == SwitchNumber) {
2145 int32_t range = max_num - min_num;
2146 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2147 return SwitchInfo::SwitchImmediate;
2148 return SwitchInfo::SwitchNone;
2149 }
2150
2151 ASSERT(typeForTable == SwitchString);
2152
2153 if (singleCharacterSwitch) {
2154 int32_t range = max_num - min_num;
2155 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2156 return SwitchInfo::SwitchCharacter;
2157 }
2158
2159 return SwitchInfo::SwitchString;
2160}
2161
2162RegisterID* CaseBlockNode::emitCodeForBlock(CodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
2163{
2164 RefPtr<LabelID> defaultLabel;
2165 Vector<RefPtr<LabelID>, 8> labelVector;
2166 Vector<ExpressionNode*, 8> literalVector;
2167 int32_t min_num = std::numeric_limits<int32_t>::max();
2168 int32_t max_num = std::numeric_limits<int32_t>::min();
2169 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
2170
2171 if (switchType != SwitchInfo::SwitchNone) {
2172 // Prepare the various labels
2173 for (uint32_t i = 0; i < literalVector.size(); i++)
2174 labelVector.append(generator.newLabel());
2175 defaultLabel = generator.newLabel();
2176 generator.beginSwitch(switchExpression, switchType);
2177 } else {
2178 // Setup jumps
2179 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
2180 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2181 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2182 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2183 labelVector.append(generator.newLabel());
2184 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2185 }
2186
2187 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
2188 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2189 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2190 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2191 labelVector.append(generator.newLabel());
2192 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2193 }
2194 defaultLabel = generator.newLabel();
2195 generator.emitJump(defaultLabel.get());
2196 }
2197
2198 RegisterID* result = 0;
2199
2200 size_t i = 0;
2201 for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) {
2202 generator.emitLabel(labelVector[i++].get());
2203 result = statementListEmitCode(list->getClause()->children(), generator, dst);
2204 }
2205
2206 if (m_defaultClause) {
2207 generator.emitLabel(defaultLabel.get());
2208 result = statementListEmitCode(m_defaultClause->children(), generator, dst);
2209 }
2210
2211 for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) {
2212 generator.emitLabel(labelVector[i++].get());
2213 result = statementListEmitCode(list->getClause()->children(), generator, dst);
2214 }
2215 if (!m_defaultClause)
2216 generator.emitLabel(defaultLabel.get());
2217
2218 ASSERT(i == labelVector.size());
2219 if (switchType != SwitchInfo::SwitchNone) {
2220 ASSERT(labelVector.size() == literalVector.size());
2221 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2222 }
2223 return result;
2224}
2225
2226// ------------------------------ SwitchNode -----------------------------------
2227
2228SwitchNode::~SwitchNode()
2229{
2230 NodeReleaser::releaseAllNodes(this);
2231}
2232
2233void SwitchNode::releaseNodes(NodeReleaser& releaser)
2234{
2235 releaser.release(m_expr);
2236 releaser.release(m_block);
2237}
2238
2239RegisterID* SwitchNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2240{
2241 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
2242
2243 RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get());
2244 RegisterID* r1 = m_block->emitCodeForBlock(generator, r0.get(), dst);
2245
2246 generator.emitLabel(scope->breakTarget());
2247 return r1;
2248}
2249
2250// ------------------------------ LabelNode ------------------------------------
2251
2252LabelNode::~LabelNode()
2253{
2254 NodeReleaser::releaseAllNodes(this);
2255}
2256
2257void LabelNode::releaseNodes(NodeReleaser& releaser)
2258{
2259 releaser.release(m_statement);
2260}
2261
2262RegisterID* LabelNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2263{
2264 if (generator.breakTarget(m_name))
2265 return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
2266
2267 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
2268 RegisterID* r0 = generator.emitNode(dst, m_statement.get());
2269
2270 generator.emitLabel(scope->breakTarget());
2271 return r0;
2272}
2273
2274// ------------------------------ ThrowNode ------------------------------------
2275
2276ThrowNode::~ThrowNode()
2277{
2278 NodeReleaser::releaseAllNodes(this);
2279}
2280
2281void ThrowNode::releaseNodes(NodeReleaser& releaser)
2282{
2283 releaser.release(m_expr);
2284}
2285
2286RegisterID* ThrowNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2287{
2288 if (dst == ignoredResult())
2289 dst = 0;
2290 RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get());
2291 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
2292 generator.emitThrow(expr.get());
2293 return dst;
2294}
2295
2296// ------------------------------ TryNode --------------------------------------
2297
2298TryNode::~TryNode()
2299{
2300 NodeReleaser::releaseAllNodes(this);
2301}
2302
2303void TryNode::releaseNodes(NodeReleaser& releaser)
2304{
2305 releaser.release(m_tryBlock);
2306 releaser.release(m_catchBlock);
2307 releaser.release(m_finallyBlock);
2308}
2309
2310RegisterID* TryNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2311{
2312 RefPtr<LabelID> tryStartLabel = generator.newLabel();
2313 RefPtr<LabelID> tryEndLabel = generator.newLabel();
2314 RefPtr<LabelID> finallyStart;
2315 RefPtr<RegisterID> finallyReturnAddr;
2316 if (m_finallyBlock) {
2317 finallyStart = generator.newLabel();
2318 finallyReturnAddr = generator.newTemporary();
2319 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
2320 }
2321 generator.emitLabel(tryStartLabel.get());
2322 generator.emitNode(dst, m_tryBlock.get());
2323 generator.emitLabel(tryEndLabel.get());
2324
2325 if (m_catchBlock) {
2326 RefPtr<LabelID> handlerEndLabel = generator.newLabel();
2327 generator.emitJump(handlerEndLabel.get());
2328 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
2329 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
2330 generator.emitNode(dst, m_catchBlock.get());
2331 generator.emitPopScope();
2332 generator.emitLabel(handlerEndLabel.get());
2333 }
2334
2335 if (m_finallyBlock) {
2336 generator.popFinallyContext();
2337 // there may be important registers live at the time we jump
2338 // to a finally block (such as for a return or throw) so we
2339 // ref the highest register ever used as a conservative
2340 // approach to not clobbering anything important
2341 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
2342 RefPtr<LabelID> finallyEndLabel = generator.newLabel();
2343 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
2344 // Use a label to record the subtle fact that sret will return to the
2345 // next instruction. sret is the only way to jump without an explicit label.
2346 generator.emitLabel(generator.newLabel().get());
2347 generator.emitJump(finallyEndLabel.get());
2348
2349 // Finally block for exception path
2350 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
2351 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
2352 // Use a label to record the subtle fact that sret will return to the
2353 // next instruction. sret is the only way to jump without an explicit label.
2354 generator.emitLabel(generator.newLabel().get());
2355 generator.emitThrow(tempExceptionRegister.get());
2356
2357 // emit the finally block itself
2358 generator.emitLabel(finallyStart.get());
2359 generator.emitNode(dst, m_finallyBlock.get());
2360 generator.emitSubroutineReturn(finallyReturnAddr.get());
2361
2362 generator.emitLabel(finallyEndLabel.get());
2363 }
2364
2365 return dst;
2366}
2367
2368// ------------------------------ ParameterNode -----------------------------
2369
2370ParameterNode::~ParameterNode()
2371{
2372 NodeReleaser::releaseAllNodes(this);
2373}
2374
2375void ParameterNode::releaseNodes(NodeReleaser& releaser)
2376{
2377 releaser.release(m_next);
2378}
2379
2380// ------------------------------ ScopeNode -----------------------------
2381
2382ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
2383 : BlockNode(globalData, children)
2384 , m_source(source)
2385 , m_features(features)
2386 , m_numConstants(numConstants)
2387{
2388 if (varStack)
2389 m_varStack = *varStack;
2390 if (funcStack)
2391 m_functionStack = *funcStack;
2392#if ENABLE(OPCODE_SAMPLING)
2393 globalData->machine->sampler()->notifyOfScope(this);
2394#endif
2395}
2396
2397// ------------------------------ ProgramNode -----------------------------
2398
2399ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2400 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
2401{
2402}
2403
2404ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2405{
2406 return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
2407}
2408
2409// ------------------------------ EvalNode -----------------------------
2410
2411EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2412 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
2413{
2414}
2415
2416RegisterID* EvalNode::emitCode(CodeGenerator& generator, RegisterID*)
2417{
2418 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2419
2420 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2421 generator.emitLoad(dstRegister.get(), jsUndefined());
2422 statementListEmitCode(children(), generator, dstRegister.get());
2423
2424 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2425 generator.emitEnd(dstRegister.get());
2426 return 0;
2427}
2428
2429void EvalNode::generateCode(ScopeChainNode* scopeChainNode)
2430{
2431 ScopeChain scopeChain(scopeChainNode);
2432 JSGlobalObject* globalObject = scopeChain.globalObject();
2433
2434 SymbolTable symbolTable;
2435 m_code.set(new EvalCodeBlock(this, globalObject, source().provider()));
2436
2437 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &symbolTable, m_code.get());
2438 generator.generate();
2439}
2440
2441EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
2442{
2443 return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
2444}
2445
2446// ------------------------------ FunctionBodyNode -----------------------------
2447
2448FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2449 : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
2450 , m_parameters(0)
2451 , m_parameterCount(0)
2452 , m_refCount(0)
2453{
2454}
2455
2456FunctionBodyNode::~FunctionBodyNode()
2457{
2458 ASSERT(!m_refCount);
2459 fastFree(m_parameters);
2460}
2461
2462void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
2463{
2464 Vector<Identifier> parameters;
2465 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
2466 parameters.append(parameter->ident());
2467 size_t count = parameters.size();
2468
2469 setSource(source);
2470 finishParsing(parameters.releaseBuffer(), count);
2471}
2472
2473void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
2474{
2475 ASSERT(!source().isNull());
2476 m_parameters = parameters;
2477 m_parameterCount = parameterCount;
2478}
2479
2480void FunctionBodyNode::mark()
2481{
2482 if (m_code)
2483 m_code->mark();
2484}
2485
2486FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
2487{
2488 return new FunctionBodyNode(globalData, children, varStack, funcStack, SourceCode(), features, numConstants);
2489}
2490
2491FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2492{
2493 return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
2494}
2495
2496void FunctionBodyNode::generateCode(ScopeChainNode* scopeChainNode)
2497{
2498 ScopeChain scopeChain(scopeChainNode);
2499 JSGlobalObject* globalObject = scopeChain.globalObject();
2500
2501 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
2502
2503 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_symbolTable, m_code.get());
2504 generator.generate();
2505}
2506
2507RegisterID* FunctionBodyNode::emitCode(CodeGenerator& generator, RegisterID*)
2508{
2509 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2510 statementListEmitCode(children(), generator, ignoredResult());
2511 if (!children().size() || !children().last()->isReturnNode()) {
2512 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
2513 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2514 generator.emitReturn(r0);
2515 }
2516 return 0;
2517}
2518
2519RegisterID* ProgramNode::emitCode(CodeGenerator& generator, RegisterID*)
2520{
2521 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2522
2523 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2524 generator.emitLoad(dstRegister.get(), jsUndefined());
2525 statementListEmitCode(children(), generator, dstRegister.get());
2526
2527 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2528 generator.emitEnd(dstRegister.get());
2529 return 0;
2530}
2531
2532void ProgramNode::generateCode(ScopeChainNode* scopeChainNode)
2533{
2534 ScopeChain scopeChain(scopeChainNode);
2535 JSGlobalObject* globalObject = scopeChain.globalObject();
2536
2537 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
2538
2539 CodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get(), m_varStack, m_functionStack);
2540 generator.generate();
2541}
2542
2543UString FunctionBodyNode::paramString() const
2544{
2545 UString s("");
2546 for (size_t pos = 0; pos < m_parameterCount; ++pos) {
2547 if (!s.isEmpty())
2548 s += ", ";
2549 s += parameters()[pos].ustring();
2550 }
2551
2552 return s;
2553}
2554
2555Identifier* FunctionBodyNode::copyParameters()
2556{
2557 Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
2558 VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
2559 return parameters;
2560}
2561
2562// ------------------------------ FuncDeclNode ---------------------------------
2563
2564FuncDeclNode::~FuncDeclNode()
2565{
2566 NodeReleaser::releaseAllNodes(this);
2567}
2568
2569void FuncDeclNode::releaseNodes(NodeReleaser& releaser)
2570{
2571 releaser.release(m_parameter);
2572 releaser.release(m_body);
2573}
2574
2575JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2576{
2577 return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2578}
2579
2580RegisterID* FuncDeclNode::emitCode(CodeGenerator&, RegisterID* dst)
2581{
2582 return dst;
2583}
2584
2585// ------------------------------ FuncExprNode ---------------------------------
2586
2587FuncExprNode::~FuncExprNode()
2588{
2589 NodeReleaser::releaseAllNodes(this);
2590}
2591
2592void FuncExprNode::releaseNodes(NodeReleaser& releaser)
2593{
2594 releaser.release(m_parameter);
2595 releaser.release(m_body);
2596}
2597
2598RegisterID* FuncExprNode::emitCode(CodeGenerator& generator, RegisterID* dst)
2599{
2600 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2601}
2602
2603JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2604{
2605 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2606
2607 /*
2608 The Identifier in a FunctionExpression can be referenced from inside
2609 the FunctionExpression's FunctionBody to allow the function to call
2610 itself recursively. However, unlike in a FunctionDeclaration, the
2611 Identifier in a FunctionExpression cannot be referenced from and
2612 does not affect the scope enclosing the FunctionExpression.
2613 */
2614
2615 if (!m_ident.isNull()) {
2616 JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
2617 func->scope().push(functionScopeObject);
2618 }
2619
2620 return func;
2621}
2622
2623} // namespace JSC
Note: See TracBrowser for help on using the repository browser.