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

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

JavaScriptCore:

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

Reviewed by Cameron Zwarich.

Fixed https://bugs.webkit.org/show_bug.cgi?id=21345
Start the debugger without reloading the inspected page

  • VM/CodeBlock.h: (JSC::EvalCodeCache::get): Updated for tweak to parsing API.
  • kjs/CollectorHeapIterator.h: Added. An iterator for the object heap, which we use to find all the live functions and recompile them.
  • kjs/DebuggerCallFrame.cpp: (JSC::DebuggerCallFrame::evaluate): Updated for tweak to parsing API.
  • kjs/FunctionConstructor.cpp: (JSC::constructFunction): Updated for tweak to parsing API.
  • kjs/JSFunction.cpp: (JSC::JSFunction::JSFunction): Try to validate our SourceCode in debug builds by ASSERTing that it's syntactically valid. This doesn't catch all SourceCode bugs, but it catches a lot of them.
  • kjs/JSGlobalObjectFunctions.cpp: (JSC::globalFuncEval): Updated for tweak to parsing API.
  • kjs/Parser.cpp: (JSC::Parser::parse):
  • kjs/Parser.h: (JSC::Parser::parse): Tweaked the parser to make it possible to parse without an ExecState, and to allow the client to specify a debugger to notify (or not) about the source we parse. This allows the inspector to recompile even though no JavaScript is executing, then notify the debugger about all source code when it's done.
  • kjs/Shell.cpp: (prettyPrintScript): Updated for tweak to parsing API.
  • kjs/SourceRange.h: (JSC::SourceCode::isNull): Added to help with ASSERTs.
  • kjs/collector.cpp: (JSC::Heap::heapAllocate): (JSC::Heap::sweep): (JSC::Heap::primaryHeapBegin): (JSC::Heap::primaryHeapEnd):
  • kjs/collector.h: (JSC::): Moved a bunch of declarations around to enable compilation of CollectorHeapIterator.
  • kjs/interpreter.cpp: (JSC::Interpreter::checkSyntax): (JSC::Interpreter::evaluate): Updated for tweak to parsing API.
  • kjs/lexer.h: (JSC::Lexer::sourceCode): BUG FIX: Calculate SourceCode ranges relative to the SourceCode range in which we're lexing, otherwise nested functions that are compiled individually get SourceCode ranges that don't reflect their nesting.
  • kjs/nodes.cpp: (JSC::FunctionBodyNode::FunctionBodyNode): (JSC::FunctionBodyNode::finishParsing): (JSC::FunctionBodyNode::create): (JSC::FunctionBodyNode::copyParameters):
  • kjs/nodes.h: (JSC::ScopeNode::setSource): (JSC::FunctionBodyNode::parameterCount): Added some helper functions for copying one FunctionBodyNode's parameters to another. The recompiler uses these when calling "finishParsing".

WebCore:

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

Reviewed by Cameron Zwarich.

Fixed https://bugs.webkit.org/show_bug.cgi?id=21345
Start the debugger without reloading the inspected page

  • WebCore.base.exp: New symbols.
  • ForwardingHeaders/kjs/CollectorHeapIterator.h: Copied from ForwardingHeaders/kjs/ustring.h.
  • ForwardingHeaders/kjs/Parser.h: Copied from ForwardingHeaders/kjs/ustring.h.
  • WebCore.xcodeproj/project.pbxproj: New forwarding headers.
  • inspector/InspectorController.cpp: (WebCore::InspectorController::setWindowVisible): (WebCore::InspectorController::windowScriptObjectAvailable): (WebCore::InspectorController::startDebugging):
  • inspector/InspectorController.h: Renamed startDebuggingAndReloadInspectedPage to startDebugging, and changed its behavior to match.
  • inspector/JavaScriptDebugListener.h:
  • inspector/JavaScriptDebugServer.cpp: (WebCore::JavaScriptDebugServer::JavaScriptDebugServer): (WebCore::JavaScriptDebugServer::addListener): (WebCore::JavaScriptDebugServer::removeListener): (WebCore::JavaScriptDebugServer::recompileAllJSFunctions): (WebCore::JavaScriptDebugServer::willAddFirstListener): (WebCore::JavaScriptDebugServer::didRemoveLastListener):
  • inspector/JavaScriptDebugServer.h: Refactored the JavaScriptDebugServer to centralize handling of adding the first listener and removing the last. Then, added a feature to recompile all JS functions in these cases. This allows us to dynamically add and remove hooks like the debugger hooks without reloading the page.
  • inspector/front-end/ScriptsPanel.js:
  • English.lproj/localizedStrings.js: Updated for startDebuggingAndReloadInspectedPage => startDebugging rename. Removed all UI that claimed that starting the debugger would reload the page.

WebKit/mac:

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

Reviewed by Cameron Zwarich.

Fixed https://bugs.webkit.org/show_bug.cgi?id=21345
Start the debugger without reloading the inspected page

WebKit/win:

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

Reviewed by Cameron Zwarich.

Fixed https://bugs.webkit.org/show_bug.cgi?id=21345
Start the debugger without reloading the inspected page

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