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

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

2008-09-14 Cameron Zwarich <[email protected]>

Reviewed by Maciej Stachowiak.

Bug 20827: the 'typeof' operator is slow
<https://bugs.webkit.org/show_bug.cgi?id=20827>

Optimize the 'typeof' operator when its result is compared to a constant
string.

This is a 5.5% speedup on the V8 Earley-Boyer test.

JavaScriptCore:

  • VM/CTI.cpp: (JSC::CTI::privateCompileMainPass):
  • VM/CodeBlock.cpp: (JSC::CodeBlock::dump):
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::emitEqualityOp):
  • VM/CodeGenerator.h:
  • VM/Machine.cpp: (JSC::jsIsObjectType): (JSC::jsIsFunctionType): (JSC::Machine::privateExecute): (JSC::Machine::cti_op_is_undefined): (JSC::Machine::cti_op_is_boolean): (JSC::Machine::cti_op_is_number): (JSC::Machine::cti_op_is_string): (JSC::Machine::cti_op_is_object): (JSC::Machine::cti_op_is_function):
  • VM/Machine.h:
  • VM/Opcode.h:
  • kjs/nodes.cpp: (JSC::BinaryOpNode::emitCode): (JSC::EqualNode::emitCode): (JSC::StrictEqualNode::emitCode):
  • kjs/nodes.h:

LayoutTests:

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