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

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

2008-11-06 Cameron Zwarich <[email protected]>

Reviewed by Geoff Garen.

Move the remaining files in the kjs subdirectory of JavaScriptCore to
a new parser subdirectory, and remove the kjs subdirectory entirely.

JavaScriptCore:

  • AllInOneFile.cpp:
  • DerivedSources.make:
  • GNUmakefile.am:
  • JavaScriptCore.pri:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.vcproj/WTF/WTF.vcproj:
  • JavaScriptCore.vcproj/jsc/jsc.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • JavaScriptCoreSources.bkl:
  • VM/CodeBlock.h:
  • VM/ExceptionHelpers.cpp:
  • VM/SamplingTool.h:
  • bytecompiler/CodeGenerator.h:
  • jsc.pro:
  • jscore.bkl:
  • kjs: Removed.
  • kjs/NodeInfo.h: Removed.
  • kjs/Parser.cpp: Removed.
  • kjs/Parser.h: Removed.
  • kjs/ResultType.h: Removed.
  • kjs/SourceCode.h: Removed.
  • kjs/SourceProvider.h: Removed.
  • kjs/grammar.y: Removed.
  • kjs/keywords.table: Removed.
  • kjs/lexer.cpp: Removed.
  • kjs/lexer.h: Removed.
  • kjs/nodes.cpp: Removed.
  • kjs/nodes.h: Removed.
  • kjs/nodes2string.cpp: Removed.
  • parser: Added.
  • parser/Grammar.y: Copied from kjs/grammar.y.
  • parser/Keywords.table: Copied from kjs/keywords.table.
  • parser/Lexer.cpp: Copied from kjs/lexer.cpp.
  • parser/Lexer.h: Copied from kjs/lexer.h.
  • parser/NodeInfo.h: Copied from kjs/NodeInfo.h.
  • parser/Nodes.cpp: Copied from kjs/nodes.cpp.
  • parser/Nodes.h: Copied from kjs/nodes.h.
  • parser/Parser.cpp: Copied from kjs/Parser.cpp.
  • parser/Parser.h: Copied from kjs/Parser.h.
  • parser/ResultType.h: Copied from kjs/ResultType.h.
  • parser/SourceCode.h: Copied from kjs/SourceCode.h.
  • parser/SourceProvider.h: Copied from kjs/SourceProvider.h.
  • parser/nodes2string.cpp: Copied from kjs/nodes2string.cpp.
  • pcre/pcre.pri:
  • pcre/pcre_exec.cpp:
  • runtime/FunctionConstructor.cpp:
  • runtime/JSActivation.h:
  • runtime/JSFunction.h:
  • runtime/JSGlobalData.cpp:
  • runtime/JSGlobalObjectFunctions.cpp:
  • runtime/JSObject.cpp: (JSC::JSObject::toNumber):
  • runtime/RegExp.cpp:

WebCore:

  • ForwardingHeaders/kjs: Removed.
  • ForwardingHeaders/kjs/Parser.h: Removed.
  • ForwardingHeaders/kjs/SavedBuiltins.h: Removed.
  • ForwardingHeaders/kjs/SourceCode.h: Removed.
  • ForwardingHeaders/kjs/SourceProvider.h: Removed.
  • ForwardingHeaders/parser: Added.
  • ForwardingHeaders/parser/Parser.h: Copied from ForwardingHeaders/kjs/Parser.h.
  • ForwardingHeaders/parser/SourceCode.h: Copied from ForwardingHeaders/kjs/SourceCode.h.
  • ForwardingHeaders/parser/SourceProvider.h: Copied from ForwardingHeaders/kjs/SourceProvider.h.
  • WebCore.pro:
  • WebCore.vcproj/WebCore.vcproj:
  • bindings/js/StringSourceProvider.h:
  • bindings/js/WorkerScriptController.cpp:
  • bridge/NP_jsobject.cpp:
  • bridge/jni/jni_jsobject.mm:
  • bridge/testbindings.pro:
  • inspector/JavaScriptDebugServer.cpp:

WebKit/mac:

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