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

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

JavaScriptCore:

2008-06-15 Darin Adler <Darin Adler>

  • API/JSCallbackFunction.cpp:
  • API/JSObjectRef.cpp:
  • DerivedSources.make:
  • GNUmakefile.am:
  • JavaScriptCore.exp:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • VM/Machine.cpp:
  • kjs/AllInOneFile.cpp:
  • kjs/ArrayPrototype.cpp: Copied from JavaScriptCore/kjs/array_object.cpp.
  • kjs/ArrayPrototype.h: Copied from JavaScriptCore/kjs/array_object.h.
  • kjs/BooleanObject.cpp: Copied from JavaScriptCore/kjs/bool_object.cpp.
  • kjs/BooleanObject.h: Copied from JavaScriptCore/kjs/bool_object.h.
  • kjs/ExecState.cpp:
  • kjs/ExecState.h:
  • kjs/FunctionPrototype.cpp: Copied from JavaScriptCore/kjs/function_object.cpp.
  • kjs/FunctionPrototype.h: Copied from JavaScriptCore/kjs/function_object.h.
  • kjs/JSArray.cpp: Copied from JavaScriptCore/kjs/array_instance.cpp.
  • kjs/JSArray.h: Copied from JavaScriptCore/kjs/array_instance.h.
  • kjs/JSFunction.cpp:
  • kjs/JSFunction.h:
  • kjs/JSGlobalObject.cpp:
  • kjs/JSImmediate.cpp:
  • kjs/JSObject.h:
  • kjs/JSString.h:
  • kjs/JSValue.h:
  • kjs/JSVariableObject.cpp:
  • kjs/MathObject.cpp: Copied from JavaScriptCore/kjs/math_object.cpp.
  • kjs/MathObject.h: Copied from JavaScriptCore/kjs/math_object.h.
  • kjs/NumberObject.cpp: Copied from JavaScriptCore/kjs/number_object.cpp.
  • kjs/NumberObject.h: Copied from JavaScriptCore/kjs/number_object.h.
  • kjs/PropertyMap.cpp: Copied from JavaScriptCore/kjs/property_map.cpp.
  • kjs/PropertyMap.h: Copied from JavaScriptCore/kjs/property_map.h.
  • kjs/PropertySlot.cpp: Copied from JavaScriptCore/kjs/property_slot.cpp.
  • kjs/PropertySlot.h: Copied from JavaScriptCore/kjs/property_slot.h.
  • kjs/RegExpObject.cpp: Copied from JavaScriptCore/kjs/regexp_object.cpp.
  • kjs/RegExpObject.h: Copied from JavaScriptCore/kjs/regexp_object.h.
  • kjs/ScopeChain.cpp: Copied from JavaScriptCore/kjs/scope_chain.cpp.
  • kjs/ScopeChain.h: Copied from JavaScriptCore/kjs/scope_chain.h.
  • kjs/ScopeChainMark.h: Copied from JavaScriptCore/kjs/scope_chain_mark.h.
  • kjs/Shell.cpp:
  • kjs/array_instance.cpp: Removed.
  • kjs/array_instance.h: Removed.
  • kjs/array_object.cpp: Removed.
  • kjs/array_object.h: Removed.
  • kjs/bool_object.cpp: Removed.
  • kjs/bool_object.h: Removed.
  • kjs/error_object.h:
  • kjs/function_object.cpp: Removed.
  • kjs/function_object.h: Removed.
  • kjs/internal.cpp:
  • kjs/math_object.cpp: Removed.
  • kjs/math_object.h: Removed.
  • kjs/nodes.cpp:
  • kjs/number_object.cpp: Removed.
  • kjs/number_object.h: Removed.
  • kjs/object_object.cpp:
  • kjs/property_map.cpp: Removed.
  • kjs/property_map.h: Removed.
  • kjs/property_slot.cpp: Removed.
  • kjs/property_slot.h: Removed.
  • kjs/regexp_object.cpp: Removed.
  • kjs/regexp_object.h: Removed.
  • kjs/scope_chain.cpp: Removed.
  • kjs/scope_chain.h: Removed.
  • kjs/scope_chain_mark.h: Removed.
  • kjs/string_object.cpp:
  • kjs/string_object.h:

WebCore:

2008-06-15 Darin Adler <Darin Adler>

  • ForwardingHeaders/kjs/ArrayPrototype.h: Copied from WebCore/ForwardingHeaders/kjs/array_object.h.
  • ForwardingHeaders/kjs/BooleanObject.h: Copied from WebCore/ForwardingHeaders/kjs/bool_object.h.
  • ForwardingHeaders/kjs/FunctionPrototype.h: Copied from WebCore/ForwardingHeaders/kjs/function_object.h.
  • ForwardingHeaders/kjs/JSArray.h: Copied from WebCore/ForwardingHeaders/kjs/array_instance.h.
  • ForwardingHeaders/kjs/PropertyMap.h: Copied from WebCore/ForwardingHeaders/kjs/property_map.h.
  • ForwardingHeaders/kjs/array_instance.h: Removed.
  • ForwardingHeaders/kjs/array_object.h: Removed.
  • ForwardingHeaders/kjs/bool_object.h: Removed.
  • ForwardingHeaders/kjs/function_object.h: Removed.
  • ForwardingHeaders/kjs/property_map.h: Removed.
  • WebCore.vcproj/WebCore.vcproj:
  • bindings/js/JSClipboardCustom.cpp:
  • bindings/js/JSDatabaseCustom.cpp:
  • bindings/js/JSJavaScriptCallFrameCustom.cpp:
  • bindings/js/kjs_events.cpp:
  • bridge/jni/jni_utility.cpp:
  • bridge/qt/qt_runtime.cpp:
  • bridge/runtime_array.cpp:

WebKit/mac:

2008-06-15 Darin Adler <Darin Adler>

  • WebView/WebView.mm:

WebKit/qt:

2008-06-15 Darin Adler <Darin Adler>

  • WebKit_pch.h:

WebKitTools:

2008-06-15 Darin Adler <Darin Adler>

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