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

Last change on this file since 47571 was 47571, checked in by Darin Adler, 16 years ago

Syntax tree nodes should use arena allocation
https://bugs.webkit.org/show_bug.cgi?id=25674

Patch by Darin Adler <Darin Adler> on 2009-08-20
Reviewed by Gavin Barraclough.

Use an actual arena now. 0.7% speedup on SunSpider.

longer needs to be used outside JavaScriptCore.

Executable.h project-internal instead of "private".

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator): Updated since VarStack
contains const Identifier* now.

  • parser/Grammar.y: Made identifiers from the lexer be const

Identifier* and updated since VarStack contains const Identifier* now.

  • parser/Lexer.cpp:

(JSC::Lexer::setCode): Pass in ParserArena, used for identifiers.
(JSC::Lexer::makeIdentifier): Changed return type to const Identifier*
and changed to call ParserArena.
(JSC::Lexer::clear): Removed the code to manage m_identifiers and
added code to set m_arena to 0.

  • parser/Lexer.h: Updated for changes above.
  • parser/NodeConstructors.h:

(JSC::ParserArenaFreeable::operator new): Added. Calls allocateFreeable
on the arena.
(JSC::ParserArenaDeletable::operator new): Changed to call the
allocateDeletable function on the arena instead of deleteWithArena.
(JSC::PropertyNode::PropertyNode): Added new constructor that makes
numeric identifiers. Some day we might want to optimize this for
integers so it doesn't create a string for each one.
(JSC::ContinueNode::ContinueNode): Initialize m_ident to nullIdentifier
since it's now a const Identifier& so it can't be left uninitialized.
(JSC::BreakNode::BreakNode): Ditto.
(JSC::CaseClauseNode::CaseClauseNode): Updated to use SourceElements*
to keep track of the statements rather than a separate statement vector.
(JSC::BlockNode::BlockNode): Ditto.
(JSC::ForInNode::ForInNode): Initialize m_ident to nullIdentifier.

  • parser/Nodes.cpp: Moved the comment explaining emitBytecode in here.

It seemed strangely out of place in the header.
(JSC::ThrowableExpressionData::emitThrowError): Added an overload for
UString as well as Identifier.
(JSC::SourceElements::singleStatement): Added.
(JSC::SourceElements::lastStatement): Added.
(JSC::RegExpNode::emitBytecode): Changed the throwError code to use
the substitution mechanism instead of doing a string append.
(JSC::SourceElements::emitBytecode): Added. Replaces the old
statementListEmitCode function, since we now keep the SourceElements
objects around.
(JSC::BlockNode::lastStatement): Added.
(JSC::BlockNode::emitBytecode): Changed to use emitBytecode instead of
statementListEmitCode.
(JSC::CaseClauseNode::emitBytecode): Added.
(JSC::CaseBlockNode::emitBytecodeForBlock): Changed to use emitBytecode
instead of statementListEmitCode.
(JSC::ScopeNodeData::ScopeNodeData): Changed to store the
SourceElements* instead of using releaseContentsIntoVector.
(JSC::ScopeNode::emitStatementsBytecode): Added.
(JSC::ScopeNode::singleStatement): Added.
(JSC::ProgramNode::emitBytecode): Call emitStatementsBytecode instead
of statementListEmitCode.
(JSC::EvalNode::emitBytecode): Ditto.
(JSC::FunctionBodyNode::emitBytecode): Call emitStatementsBytecode
insetad of statementListEmitCode and check for the return node using
the new functions.

  • parser/Nodes.h: Changed VarStack to store const Identifier* instead

of Identifier and rely on the arena to control lifetime. Added a new
ParserArenaFreeable class. Made ParserArenaDeletable inherit from
FastAllocBase instead of having its own operator new. Base the Node
class on ParserArenaFreeable. Changed the various Node classes
to use const Identifier& instead of Identifier to avoid the need to
call their destructors and allow them to function as "freeable" in the
arena. Removed extraneous JSC_FAST_CALL on definitions of inline functions.
Changed ElementNode, PropertyNode, ArgumentsNode, ParameterNode,
CaseClauseNode, ClauseListNode, and CaseBlockNode to use ParserArenaFreeable
as a base class since they do not descend from Node. Eliminated the
StatementVector type and instead have various classes use SourceElements*
instead of StatementVector. This prevents those classes from having to
use ParserArenaDeletable to make sure the vector destructor is called.

  • parser/Parser.cpp:

(JSC::Parser::parse): Pass the arena to the lexer.

  • parser/Parser.h: Added an include of ParserArena.h, which is no longer

included by Nodes.h.
(JSC::Parser::parseFunctionFromGlobalCode): Changed to use the
singleStatement function, since there is no longer any children function.
Removed some unneeded use of RefPtr.

  • parser/ParserArena.cpp:

(JSC::ParserArena::ParserArena): Added. Initializes the new members,
m_freeableMemory, m_freeablePoolEnd, and m_identifiers.
(JSC::ParserArena::freeablePool): Added. Computes the pool pointer,
since we store only the current pointer and the end of pool pointer.
(JSC::ParserArena::deallocateObjects): Added. Contains the common
memory-deallocation logic used by both the destructor and the
reset function.
(JSC::ParserArena::~ParserArena): Changed to call deallocateObjects.
(JSC::ParserArena::reset): Ditto. Also added code to zero out the
new structures, and switched to use clear() instead of shrink(0) since
we don't really reuse arenas.
(JSC::ParserArena::makeNumericIdentifier): Added.
(JSC::ParserArena::allocateFreeablePool): Added. Used when the pool
is empty.
(JSC::ParserArena::isEmpty): Added. No longer inline, which is fine
since this is used only for assertions at the moment.

  • parser/ParserArena.h: Added an actual arena of "freeable" objects,

ones that don't need destructors to be called. Also added a separate
IdentifierArena object, a segmented vector of identifiers that used
to be in the Lexer.

  • runtime/Executable.h: Moved the definition of the

FunctionExecutable::make function here. It can't go in JSFunction.h
since that header has to be used outside JavaScriptCore and so can't
include this, which includes Nodes.h. The function could be moved
elswhere if we don't want to include JSFunction.h in this header, but
for now this seems to be the best place.

  • runtime/JSFunction.h: Removed the include of Executable.h and

definition of the FunctionExecutable::make function.

  • wtf/FastMalloc.cpp: Fixed an incorrect comment.
  • Property svn:eol-style set to native
File size: 87.1 KB
Line 
1/*
2* Copyright (C) 1999-2002 Harri Porten ([email protected])
3* Copyright (C) 2001 Peter Kelly ([email protected])
4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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#include "NodeConstructors.h"
29
30#include "BytecodeGenerator.h"
31#include "CallFrame.h"
32#include "Debugger.h"
33#include "JIT.h"
34#include "JSFunction.h"
35#include "JSGlobalObject.h"
36#include "JSStaticScopeObject.h"
37#include "LabelScope.h"
38#include "Lexer.h"
39#include "Operations.h"
40#include "Parser.h"
41#include "PropertyNameArray.h"
42#include "RegExpObject.h"
43#include "SamplingTool.h"
44#include <wtf/Assertions.h>
45#include <wtf/RefCountedLeakCounter.h>
46#include <wtf/Threading.h>
47
48using namespace WTF;
49
50namespace JSC {
51
52/*
53 Details of the emitBytecode function.
54
55 Return value: The register holding the production's value.
56 dst: An optional parameter specifying the most efficient destination at
57 which to store the production's value. The callee must honor dst.
58
59 The dst argument provides for a crude form of copy propagation. For example,
60
61 x = 1
62
63 becomes
64
65 load r[x], 1
66
67 instead of
68
69 load r0, 1
70 mov r[x], r0
71
72 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
73*/
74
75// ------------------------------ ThrowableExpressionData --------------------------------
76
77static void substitute(UString& string, const UString& substring)
78{
79 int position = string.find("%s");
80 ASSERT(position != -1);
81 UString newString = string.substr(0, position);
82 newString.append(substring);
83 newString.append(string.substr(position + 2));
84 string = newString;
85}
86
87RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message)
88{
89 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
90 RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
91 generator.emitThrow(exception);
92 return exception;
93}
94
95RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label)
96{
97 UString message = messageTemplate;
98 substitute(message, label);
99 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
100 RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
101 generator.emitThrow(exception);
102 return exception;
103}
104
105inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label)
106{
107 return emitThrowError(generator, type, messageTemplate, label.ustring());
108}
109
110// ------------------------------ StatementNode --------------------------------
111
112void StatementNode::setLoc(int firstLine, int lastLine)
113{
114 m_line = firstLine;
115 m_lastLine = lastLine;
116}
117
118// ------------------------------ SourceElements --------------------------------
119
120void SourceElements::append(StatementNode* statement)
121{
122 if (statement->isEmptyStatement())
123 return;
124 m_statements.append(statement);
125}
126
127inline StatementNode* SourceElements::singleStatement() const
128{
129 size_t size = m_statements.size();
130 return size == 1 ? m_statements[0] : 0;
131}
132
133inline StatementNode* SourceElements::lastStatement() const
134{
135 size_t size = m_statements.size();
136 return size ? m_statements[size - 1] : 0;
137}
138
139// ------------------------------ NullNode -------------------------------------
140
141RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
142{
143 if (dst == generator.ignoredResult())
144 return 0;
145 return generator.emitLoad(dst, jsNull());
146}
147
148// ------------------------------ BooleanNode ----------------------------------
149
150RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
151{
152 if (dst == generator.ignoredResult())
153 return 0;
154 return generator.emitLoad(dst, m_value);
155}
156
157// ------------------------------ NumberNode -----------------------------------
158
159RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
160{
161 if (dst == generator.ignoredResult())
162 return 0;
163 return generator.emitLoad(dst, m_value);
164}
165
166// ------------------------------ StringNode -----------------------------------
167
168RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
169{
170 if (dst == generator.ignoredResult())
171 return 0;
172 return generator.emitLoad(dst, m_value);
173}
174
175// ------------------------------ RegExpNode -----------------------------------
176
177RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
178{
179 RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring());
180 if (!regExp->isValid())
181 return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage());
182 if (dst == generator.ignoredResult())
183 return 0;
184 return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
185}
186
187// ------------------------------ ThisNode -------------------------------------
188
189RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
190{
191 if (dst == generator.ignoredResult())
192 return 0;
193 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
194}
195
196// ------------------------------ ResolveNode ----------------------------------
197
198bool ResolveNode::isPure(BytecodeGenerator& generator) const
199{
200 return generator.isLocal(m_ident);
201}
202
203RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
204{
205 if (RegisterID* local = generator.registerFor(m_ident)) {
206 if (dst == generator.ignoredResult())
207 return 0;
208 return generator.moveToDestinationIfNeeded(dst, local);
209 }
210
211 generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
212 return generator.emitResolve(generator.finalDestination(dst), m_ident);
213}
214
215// ------------------------------ ArrayNode ------------------------------------
216
217RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
218{
219 // FIXME: Should we put all of this code into emitNewArray?
220
221 unsigned length = 0;
222 ElementNode* firstPutElement;
223 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
224 if (firstPutElement->elision())
225 break;
226 ++length;
227 }
228
229 if (!firstPutElement && !m_elision)
230 return generator.emitNewArray(generator.finalDestination(dst), m_element);
231
232 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element);
233
234 for (ElementNode* n = firstPutElement; n; n = n->next()) {
235 RegisterID* value = generator.emitNode(n->value());
236 length += n->elision();
237 generator.emitPutByIndex(array.get(), length++, value);
238 }
239
240 if (m_elision) {
241 RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
242 generator.emitPutById(array.get(), generator.propertyNames().length, value);
243 }
244
245 return generator.moveToDestinationIfNeeded(dst, array.get());
246}
247
248bool ArrayNode::isSimpleArray() const
249{
250 if (m_elision || m_optional)
251 return false;
252 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
253 if (ptr->elision())
254 return false;
255 }
256 return true;
257}
258
259ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const
260{
261 ASSERT(!m_elision && !m_optional);
262 ElementNode* ptr = m_element;
263 if (!ptr)
264 return 0;
265 ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value());
266 ArgumentListNode* tail = head;
267 ptr = ptr->next();
268 for (; ptr; ptr = ptr->next()) {
269 ASSERT(!ptr->elision());
270 tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value());
271 }
272 return head;
273}
274
275// ------------------------------ ObjectLiteralNode ----------------------------
276
277RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
278{
279 if (!m_list) {
280 if (dst == generator.ignoredResult())
281 return 0;
282 return generator.emitNewObject(generator.finalDestination(dst));
283 }
284 return generator.emitNode(dst, m_list);
285}
286
287// ------------------------------ PropertyListNode -----------------------------
288
289RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
290{
291 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
292
293 generator.emitNewObject(newObj.get());
294
295 for (PropertyListNode* p = this; p; p = p->m_next) {
296 RegisterID* value = generator.emitNode(p->m_node->m_assign);
297
298 switch (p->m_node->m_type) {
299 case PropertyNode::Constant: {
300 generator.emitPutById(newObj.get(), p->m_node->name(), value);
301 break;
302 }
303 case PropertyNode::Getter: {
304 generator.emitPutGetter(newObj.get(), p->m_node->name(), value);
305 break;
306 }
307 case PropertyNode::Setter: {
308 generator.emitPutSetter(newObj.get(), p->m_node->name(), value);
309 break;
310 }
311 default:
312 ASSERT_NOT_REACHED();
313 }
314 }
315
316 return generator.moveToDestinationIfNeeded(dst, newObj.get());
317}
318
319// ------------------------------ BracketAccessorNode --------------------------------
320
321RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
322{
323 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
324 RegisterID* property = generator.emitNode(m_subscript);
325 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
326 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
327}
328
329// ------------------------------ DotAccessorNode --------------------------------
330
331RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
332{
333 RegisterID* base = generator.emitNode(m_base);
334 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
335 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
336}
337
338// ------------------------------ ArgumentListNode -----------------------------
339
340RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
341{
342 ASSERT(m_expr);
343 return generator.emitNode(dst, m_expr);
344}
345
346// ------------------------------ NewExprNode ----------------------------------
347
348RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
349{
350 RefPtr<RegisterID> func = generator.emitNode(m_expr);
351 return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset());
352}
353
354// ------------------------------ EvalFunctionCallNode ----------------------------------
355
356RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
357{
358 RefPtr<RegisterID> func = generator.tempDestination(dst);
359 RefPtr<RegisterID> thisRegister = generator.newTemporary();
360 generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
361 generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
362 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
363}
364
365// ------------------------------ FunctionCallValueNode ----------------------------------
366
367RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
368{
369 RefPtr<RegisterID> func = generator.emitNode(m_expr);
370 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
371 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
372}
373
374// ------------------------------ FunctionCallResolveNode ----------------------------------
375
376RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
377{
378 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
379 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
380 return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
381 }
382
383 int index = 0;
384 size_t depth = 0;
385 JSObject* globalObject = 0;
386 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
387 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
388 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
389 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
390 }
391
392 RefPtr<RegisterID> func = generator.newTemporary();
393 RefPtr<RegisterID> thisRegister = generator.newTemporary();
394 int identifierStart = divot() - startOffset();
395 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
396 generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident);
397 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
398}
399
400// ------------------------------ FunctionCallBracketNode ----------------------------------
401
402RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
403{
404 RefPtr<RegisterID> base = generator.emitNode(m_base);
405 RegisterID* property = generator.emitNode(m_subscript);
406 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
407 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
408 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
409 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
410}
411
412// ------------------------------ FunctionCallDotNode ----------------------------------
413
414RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
415{
416 RefPtr<RegisterID> function = generator.tempDestination(dst);
417 RefPtr<RegisterID> thisRegister = generator.newTemporary();
418 generator.emitNode(thisRegister.get(), m_base);
419 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
420 generator.emitMethodCheck();
421 generator.emitGetById(function.get(), thisRegister.get(), m_ident);
422 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
423}
424
425RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
426{
427 RefPtr<Label> realCall = generator.newLabel();
428 RefPtr<Label> end = generator.newLabel();
429 RefPtr<RegisterID> base = generator.emitNode(m_base);
430 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
431 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
432 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
433 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
434 {
435 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
436 RefPtr<RegisterID> thisRegister = generator.newTemporary();
437 ArgumentListNode* oldList = m_args->m_listNode;
438 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
439 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
440 m_args->m_listNode = m_args->m_listNode->m_next;
441 } else
442 generator.emitLoad(thisRegister.get(), jsNull());
443
444 generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
445 generator.emitJump(end.get());
446 m_args->m_listNode = oldList;
447 }
448 generator.emitLabel(realCall.get());
449 {
450 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
451 generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
452 }
453 generator.emitLabel(end.get());
454 return finalDestination.get();
455}
456
457static bool areTrivialApplyArguments(ArgumentsNode* args)
458{
459 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
460 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
461}
462
463RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
464{
465 // A few simple cases can be trivially handled as ordinary function calls.
466 // function.apply(), function.apply(arg) -> identical to function.call
467 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
468 bool mayBeCall = areTrivialApplyArguments(m_args);
469
470 RefPtr<Label> realCall = generator.newLabel();
471 RefPtr<Label> end = generator.newLabel();
472 RefPtr<RegisterID> base = generator.emitNode(m_base);
473 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
474 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
475 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
476 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
477 {
478 if (mayBeCall) {
479 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
480 RefPtr<RegisterID> thisRegister = generator.newTemporary();
481 ArgumentListNode* oldList = m_args->m_listNode;
482 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
483 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
484 m_args->m_listNode = m_args->m_listNode->m_next;
485 if (m_args->m_listNode) {
486 ASSERT(m_args->m_listNode->m_expr->isSimpleArray());
487 ASSERT(!m_args->m_listNode->m_next);
488 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData());
489 }
490 } else
491 generator.emitLoad(thisRegister.get(), jsNull());
492 generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
493 m_args->m_listNode = oldList;
494 } else {
495 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
496 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
497 RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
498 RefPtr<RegisterID> thisRegister = generator.newTemporary();
499 RefPtr<RegisterID> argsRegister = generator.newTemporary();
500 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
501 ArgumentListNode* args = m_args->m_listNode->m_next;
502 bool isArgumentsApply = false;
503 if (args->m_expr->isResolveNode()) {
504 ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr);
505 isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier());
506 if (isArgumentsApply)
507 generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments());
508 }
509 if (!isArgumentsApply)
510 generator.emitNode(argsRegister.get(), args->m_expr);
511 while ((args = args->m_next))
512 generator.emitNode(args->m_expr);
513
514 generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
515 generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
516 }
517 generator.emitJump(end.get());
518 }
519 generator.emitLabel(realCall.get());
520 {
521 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
522 generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
523 }
524 generator.emitLabel(end.get());
525 return finalDestination.get();
526}
527
528// ------------------------------ PostfixResolveNode ----------------------------------
529
530static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
531{
532 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
533}
534
535static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
536{
537 if (srcDst == dst)
538 return generator.emitToJSNumber(dst, srcDst);
539 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
540}
541
542RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
543{
544 if (RegisterID* local = generator.registerFor(m_ident)) {
545 if (generator.isLocalConstant(m_ident)) {
546 if (dst == generator.ignoredResult())
547 return 0;
548 return generator.emitToJSNumber(generator.finalDestination(dst), local);
549 }
550
551 if (dst == generator.ignoredResult())
552 return emitPreIncOrDec(generator, local, m_operator);
553 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
554 }
555
556 int index = 0;
557 size_t depth = 0;
558 JSObject* globalObject = 0;
559 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
560 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
561 RegisterID* oldValue;
562 if (dst == generator.ignoredResult()) {
563 oldValue = 0;
564 emitPreIncOrDec(generator, value.get(), m_operator);
565 } else {
566 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
567 }
568 generator.emitPutScopedVar(depth, index, value.get(), globalObject);
569 return oldValue;
570 }
571
572 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
573 RefPtr<RegisterID> value = generator.newTemporary();
574 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
575 RegisterID* oldValue;
576 if (dst == generator.ignoredResult()) {
577 oldValue = 0;
578 emitPreIncOrDec(generator, value.get(), m_operator);
579 } else {
580 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
581 }
582 generator.emitPutById(base.get(), m_ident, value.get());
583 return oldValue;
584}
585
586// ------------------------------ PostfixBracketNode ----------------------------------
587
588RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
589{
590 RefPtr<RegisterID> base = generator.emitNode(m_base);
591 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
592
593 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
594 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
595 RegisterID* oldValue;
596 if (dst == generator.ignoredResult()) {
597 oldValue = 0;
598 if (m_operator == OpPlusPlus)
599 generator.emitPreInc(value.get());
600 else
601 generator.emitPreDec(value.get());
602 } else {
603 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
604 }
605 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
606 generator.emitPutByVal(base.get(), property.get(), value.get());
607 return oldValue;
608}
609
610// ------------------------------ PostfixDotNode ----------------------------------
611
612RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
613{
614 RefPtr<RegisterID> base = generator.emitNode(m_base);
615
616 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
617 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
618 RegisterID* oldValue;
619 if (dst == generator.ignoredResult()) {
620 oldValue = 0;
621 if (m_operator == OpPlusPlus)
622 generator.emitPreInc(value.get());
623 else
624 generator.emitPreDec(value.get());
625 } else {
626 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
627 }
628 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
629 generator.emitPutById(base.get(), m_ident, value.get());
630 return oldValue;
631}
632
633// ------------------------------ PostfixErrorNode -----------------------------------
634
635RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
636{
637 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
638 ? "Postfix ++ operator applied to value that is not a reference."
639 : "Postfix -- operator applied to value that is not a reference.");
640}
641
642// ------------------------------ DeleteResolveNode -----------------------------------
643
644RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
645{
646 if (generator.registerFor(m_ident))
647 return generator.emitLoad(generator.finalDestination(dst), false);
648
649 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
650 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
651 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
652}
653
654// ------------------------------ DeleteBracketNode -----------------------------------
655
656RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
657{
658 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
659 RegisterID* r1 = generator.emitNode(m_subscript);
660
661 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
662 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
663}
664
665// ------------------------------ DeleteDotNode -----------------------------------
666
667RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
668{
669 RegisterID* r0 = generator.emitNode(m_base);
670
671 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
672 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
673}
674
675// ------------------------------ DeleteValueNode -----------------------------------
676
677RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
678{
679 generator.emitNode(generator.ignoredResult(), m_expr);
680
681 // delete on a non-location expression ignores the value and returns true
682 return generator.emitLoad(generator.finalDestination(dst), true);
683}
684
685// ------------------------------ VoidNode -------------------------------------
686
687RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
688{
689 if (dst == generator.ignoredResult()) {
690 generator.emitNode(generator.ignoredResult(), m_expr);
691 return 0;
692 }
693 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
694 return generator.emitLoad(dst, jsUndefined());
695}
696
697// ------------------------------ TypeOfValueNode -----------------------------------
698
699RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
700{
701 if (RegisterID* local = generator.registerFor(m_ident)) {
702 if (dst == generator.ignoredResult())
703 return 0;
704 return generator.emitTypeOf(generator.finalDestination(dst), local);
705 }
706
707 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
708 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
709 if (dst == generator.ignoredResult())
710 return 0;
711 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
712}
713
714// ------------------------------ TypeOfValueNode -----------------------------------
715
716RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
717{
718 if (dst == generator.ignoredResult()) {
719 generator.emitNode(generator.ignoredResult(), m_expr);
720 return 0;
721 }
722 RefPtr<RegisterID> src = generator.emitNode(m_expr);
723 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
724}
725
726// ------------------------------ PrefixResolveNode ----------------------------------
727
728RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
729{
730 if (RegisterID* local = generator.registerFor(m_ident)) {
731 if (generator.isLocalConstant(m_ident)) {
732 if (dst == generator.ignoredResult())
733 return 0;
734 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
735 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
736 }
737
738 emitPreIncOrDec(generator, local, m_operator);
739 return generator.moveToDestinationIfNeeded(dst, local);
740 }
741
742 int index = 0;
743 size_t depth = 0;
744 JSObject* globalObject = 0;
745 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
746 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
747 emitPreIncOrDec(generator, propDst.get(), m_operator);
748 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
749 return generator.moveToDestinationIfNeeded(dst, propDst.get());
750 }
751
752 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
753 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
754 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
755 emitPreIncOrDec(generator, propDst.get(), m_operator);
756 generator.emitPutById(base.get(), m_ident, propDst.get());
757 return generator.moveToDestinationIfNeeded(dst, propDst.get());
758}
759
760// ------------------------------ PrefixBracketNode ----------------------------------
761
762RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
763{
764 RefPtr<RegisterID> base = generator.emitNode(m_base);
765 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
766 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
767
768 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
769 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
770 if (m_operator == OpPlusPlus)
771 generator.emitPreInc(value);
772 else
773 generator.emitPreDec(value);
774 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
775 generator.emitPutByVal(base.get(), property.get(), value);
776 return generator.moveToDestinationIfNeeded(dst, propDst.get());
777}
778
779// ------------------------------ PrefixDotNode ----------------------------------
780
781RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
782{
783 RefPtr<RegisterID> base = generator.emitNode(m_base);
784 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
785
786 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
787 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
788 if (m_operator == OpPlusPlus)
789 generator.emitPreInc(value);
790 else
791 generator.emitPreDec(value);
792 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
793 generator.emitPutById(base.get(), m_ident, value);
794 return generator.moveToDestinationIfNeeded(dst, propDst.get());
795}
796
797// ------------------------------ PrefixErrorNode -----------------------------------
798
799RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
800{
801 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
802 ? "Prefix ++ operator applied to value that is not a reference."
803 : "Prefix -- operator applied to value that is not a reference.");
804}
805
806// ------------------------------ Unary Operation Nodes -----------------------------------
807
808RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
809{
810 RegisterID* src = generator.emitNode(m_expr);
811 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
812}
813
814// ------------------------------ Binary Operation Nodes -----------------------------------
815
816// BinaryOpNode::emitStrcat:
817//
818// This node generates an op_strcat operation. This opcode can handle concatenation of three or
819// more values, where we can determine a set of separate op_add operations would be operating on
820// string values.
821//
822// This function expects to be operating on a graph of AST nodes looking something like this:
823//
824// (a)... (b)
825// \ /
826// (+) (c)
827// \ /
828// [d] ((+))
829// \ /
830// [+=]
831//
832// The assignment operation is optional, if it exists the register holding the value on the
833// lefthand side of the assignment should be passing as the optional 'lhs' argument.
834//
835// The method should be called on the node at the root of the tree of regular binary add
836// operations (marked in the diagram with a double set of parentheses). This node must
837// be performing a string concatenation (determined by statically detecting that at least
838// one child must be a string).
839//
840// Since the minimum number of values being concatenated together is expected to be 3, if
841// a lhs to a concatenating assignment is not provided then the root add should have at
842// least one left child that is also an add that can be determined to be operating on strings.
843//
844RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
845{
846 ASSERT(isAdd());
847 ASSERT(resultDescriptor().definitelyIsString());
848
849 // Create a list of expressions for all the adds in the tree of nodes we can convert into
850 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
851 // added first, and the leftmost child is never added, so the vector produced for the
852 // example above will be [ c, b ].
853 Vector<ExpressionNode*, 16> reverseExpressionList;
854 reverseExpressionList.append(m_expr2);
855
856 // Examine the left child of the add. So long as this is a string add, add its right-child
857 // to the list, and keep processing along the left fork.
858 ExpressionNode* leftMostAddChild = m_expr1;
859 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
860 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
861 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
862 }
863
864 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
865
866 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
867 // We could possibly avoid this (the lhs is converted last anyway, we could let the
868 // op_strcat node handle its conversion if required).
869 if (lhs)
870 temporaryRegisters.append(generator.newTemporary());
871
872 // Emit code for the leftmost node ((a) in the example).
873 temporaryRegisters.append(generator.newTemporary());
874 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
875 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
876
877 // Note on ordering of conversions:
878 //
879 // We maintain the same ordering of conversions as we would see if the concatenations
880 // was performed as a sequence of adds (otherwise this optimization could change
881 // behaviour should an object have been provided a valueOf or toString method).
882 //
883 // Considering the above example, the sequnce of execution is:
884 // * evaluate operand (a)
885 // * evaluate operand (b)
886 // * convert (a) to primitive <- (this would be triggered by the first add)
887 // * convert (b) to primitive <- (ditto)
888 // * evaluate operand (c)
889 // * convert (c) to primitive <- (this would be triggered by the second add)
890 // And optionally, if there is an assignment:
891 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
892 //
893 // As such we do not plant an op to convert the leftmost child now. Instead, use
894 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
895 // once the second node has been generated. However, if the leftmost child is an
896 // immediate we can trivially determine that no conversion will be required.
897 // If this is the case
898 if (leftMostAddChild->isString())
899 leftMostAddChildTempRegister = 0;
900
901 while (reverseExpressionList.size()) {
902 ExpressionNode* node = reverseExpressionList.last();
903 reverseExpressionList.removeLast();
904
905 // Emit the code for the current node.
906 temporaryRegisters.append(generator.newTemporary());
907 generator.emitNode(temporaryRegisters.last().get(), node);
908
909 // On the first iteration of this loop, when we first reach this point we have just
910 // generated the second node, which means it is time to convert the leftmost operand.
911 if (leftMostAddChildTempRegister) {
912 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
913 leftMostAddChildTempRegister = 0; // Only do this once.
914 }
915 // Plant a conversion for this node, if necessary.
916 if (!node->isString())
917 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
918 }
919 ASSERT(temporaryRegisters.size() >= 3);
920
921 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
922 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
923 if (emitExpressionInfoForMe)
924 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
925
926 // If there is an assignment convert the lhs now. This will also copy lhs to
927 // the temporary register we allocated for it.
928 if (lhs)
929 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
930
931 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
932}
933
934RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
935{
936 OpcodeID opcodeID = this->opcodeID();
937
938 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString())
939 return emitStrcat(generator, dst);
940
941 if (opcodeID == op_neq) {
942 if (m_expr1->isNull() || m_expr2->isNull()) {
943 RefPtr<RegisterID> src = generator.tempDestination(dst);
944 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
945 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
946 }
947 }
948
949 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
950 RegisterID* src2 = generator.emitNode(m_expr2);
951 return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
952}
953
954RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
955{
956 if (m_expr1->isNull() || m_expr2->isNull()) {
957 RefPtr<RegisterID> src = generator.tempDestination(dst);
958 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
959 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
960 }
961
962 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
963 RegisterID* src2 = generator.emitNode(m_expr2);
964 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
965}
966
967RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
968{
969 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
970 RegisterID* src2 = generator.emitNode(m_expr2);
971 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
972}
973
974RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
975{
976 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
977 RegisterID* src2 = generator.emitNode(m_expr2);
978 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
979}
980
981RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
982{
983 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
984 RegisterID* src2 = generator.emitNode(m_expr2);
985 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
986 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
987}
988
989RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
990{
991 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
992 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
993
994 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
995 generator.emitGetByIdExceptionInfo(op_instanceof);
996 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
997
998 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
999 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
1000}
1001
1002// ------------------------------ LogicalOpNode ----------------------------
1003
1004RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1005{
1006 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1007 RefPtr<Label> target = generator.newLabel();
1008
1009 generator.emitNode(temp.get(), m_expr1);
1010 if (m_operator == OpLogicalAnd)
1011 generator.emitJumpIfFalse(temp.get(), target.get());
1012 else
1013 generator.emitJumpIfTrue(temp.get(), target.get());
1014 generator.emitNode(temp.get(), m_expr2);
1015 generator.emitLabel(target.get());
1016
1017 return generator.moveToDestinationIfNeeded(dst, temp.get());
1018}
1019
1020// ------------------------------ ConditionalNode ------------------------------
1021
1022RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1023{
1024 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1025 RefPtr<Label> beforeElse = generator.newLabel();
1026 RefPtr<Label> afterElse = generator.newLabel();
1027
1028 RegisterID* cond = generator.emitNode(m_logical);
1029 generator.emitJumpIfFalse(cond, beforeElse.get());
1030
1031 generator.emitNode(newDst.get(), m_expr1);
1032 generator.emitJump(afterElse.get());
1033
1034 generator.emitLabel(beforeElse.get());
1035 generator.emitNode(newDst.get(), m_expr2);
1036
1037 generator.emitLabel(afterElse.get());
1038
1039 return newDst.get();
1040}
1041
1042// ------------------------------ ReadModifyResolveNode -----------------------------------
1043
1044// FIXME: should this be moved to be a method on BytecodeGenerator?
1045static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1046{
1047 OpcodeID opcodeID;
1048 switch (oper) {
1049 case OpMultEq:
1050 opcodeID = op_mul;
1051 break;
1052 case OpDivEq:
1053 opcodeID = op_div;
1054 break;
1055 case OpPlusEq:
1056 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1057 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1058 opcodeID = op_add;
1059 break;
1060 case OpMinusEq:
1061 opcodeID = op_sub;
1062 break;
1063 case OpLShift:
1064 opcodeID = op_lshift;
1065 break;
1066 case OpRShift:
1067 opcodeID = op_rshift;
1068 break;
1069 case OpURShift:
1070 opcodeID = op_urshift;
1071 break;
1072 case OpAndEq:
1073 opcodeID = op_bitand;
1074 break;
1075 case OpXOrEq:
1076 opcodeID = op_bitxor;
1077 break;
1078 case OpOrEq:
1079 opcodeID = op_bitor;
1080 break;
1081 case OpModEq:
1082 opcodeID = op_mod;
1083 break;
1084 default:
1085 ASSERT_NOT_REACHED();
1086 return dst;
1087 }
1088
1089 RegisterID* src2 = generator.emitNode(m_right);
1090
1091 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1092 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1093 if (emitExpressionInfoForMe)
1094 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
1095
1096 return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1097}
1098
1099RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1100{
1101 if (RegisterID* local = generator.registerFor(m_ident)) {
1102 if (generator.isLocalConstant(m_ident)) {
1103 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1104 }
1105
1106 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1107 RefPtr<RegisterID> result = generator.newTemporary();
1108 generator.emitMove(result.get(), local);
1109 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1110 generator.emitMove(local, result.get());
1111 return generator.moveToDestinationIfNeeded(dst, result.get());
1112 }
1113
1114 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1115 return generator.moveToDestinationIfNeeded(dst, result);
1116 }
1117
1118 int index = 0;
1119 size_t depth = 0;
1120 JSObject* globalObject = 0;
1121 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1122 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
1123 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1124 generator.emitPutScopedVar(depth, index, result, globalObject);
1125 return result;
1126 }
1127
1128 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
1129 generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
1130 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
1131 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
1132 return generator.emitPutById(base.get(), m_ident, result);
1133}
1134
1135// ------------------------------ AssignResolveNode -----------------------------------
1136
1137RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1138{
1139 if (RegisterID* local = generator.registerFor(m_ident)) {
1140 if (generator.isLocalConstant(m_ident))
1141 return generator.emitNode(dst, m_right);
1142
1143 RegisterID* result = generator.emitNode(local, m_right);
1144 return generator.moveToDestinationIfNeeded(dst, result);
1145 }
1146
1147 int index = 0;
1148 size_t depth = 0;
1149 JSObject* globalObject = 0;
1150 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1151 if (dst == generator.ignoredResult())
1152 dst = 0;
1153 RegisterID* value = generator.emitNode(dst, m_right);
1154 generator.emitPutScopedVar(depth, index, value, globalObject);
1155 return value;
1156 }
1157
1158 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1159 if (dst == generator.ignoredResult())
1160 dst = 0;
1161 RegisterID* value = generator.emitNode(dst, m_right);
1162 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1163 return generator.emitPutById(base.get(), m_ident, value);
1164}
1165
1166// ------------------------------ AssignDotNode -----------------------------------
1167
1168RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1169{
1170 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1171 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1172 RegisterID* result = generator.emitNode(value.get(), m_right);
1173 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1174 generator.emitPutById(base.get(), m_ident, result);
1175 return generator.moveToDestinationIfNeeded(dst, result);
1176}
1177
1178// ------------------------------ ReadModifyDotNode -----------------------------------
1179
1180RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1181{
1182 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1183
1184 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1185 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1186 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1187
1188 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1189 return generator.emitPutById(base.get(), m_ident, updatedValue);
1190}
1191
1192// ------------------------------ AssignErrorNode -----------------------------------
1193
1194RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1195{
1196 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
1197}
1198
1199// ------------------------------ AssignBracketNode -----------------------------------
1200
1201RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1202{
1203 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1204 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1205 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1206 RegisterID* result = generator.emitNode(value.get(), m_right);
1207
1208 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1209 generator.emitPutByVal(base.get(), property.get(), result);
1210 return generator.moveToDestinationIfNeeded(dst, result);
1211}
1212
1213// ------------------------------ ReadModifyBracketNode -----------------------------------
1214
1215RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1216{
1217 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1218 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1219
1220 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1221 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1222 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1223
1224 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1225 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1226
1227 return updatedValue;
1228}
1229
1230// ------------------------------ CommaNode ------------------------------------
1231
1232RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1233{
1234 ASSERT(m_expressions.size() > 1);
1235 for (size_t i = 0; i < m_expressions.size() - 1; i++)
1236 generator.emitNode(generator.ignoredResult(), m_expressions[i]);
1237 return generator.emitNode(dst, m_expressions.last());
1238}
1239
1240// ------------------------------ ConstDeclNode ------------------------------------
1241
1242RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1243{
1244 if (RegisterID* local = generator.constRegisterFor(m_ident)) {
1245 if (!m_init)
1246 return local;
1247
1248 return generator.emitNode(local, m_init);
1249 }
1250
1251 if (generator.codeType() != EvalCode) {
1252 if (m_init)
1253 return generator.emitNode(m_init);
1254 else
1255 return generator.emitResolve(generator.newTemporary(), m_ident);
1256 }
1257 // FIXME: While this code should only be hit in eval code, it will potentially
1258 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1259 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1260 RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1261 return generator.emitPutById(base.get(), m_ident, value);
1262}
1263
1264RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1265{
1266 RegisterID* result = 0;
1267 for (ConstDeclNode* n = this; n; n = n->m_next)
1268 result = n->emitCodeSingle(generator);
1269
1270 return result;
1271}
1272
1273// ------------------------------ ConstStatementNode -----------------------------
1274
1275RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1276{
1277 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1278 return generator.emitNode(m_next);
1279}
1280
1281// ------------------------------ SourceElements -------------------------------
1282
1283inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1284{
1285 size_t size = m_statements.size();
1286 for (size_t i = 0; i < size; ++i)
1287 generator.emitNode(dst, m_statements[i]);
1288}
1289
1290// ------------------------------ BlockNode ------------------------------------
1291
1292inline StatementNode* BlockNode::lastStatement() const
1293{
1294 return m_statements ? m_statements->lastStatement() : 0;
1295}
1296
1297RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1298{
1299 if (m_statements)
1300 m_statements->emitBytecode(generator, dst);
1301 return 0;
1302}
1303
1304// ------------------------------ EmptyStatementNode ---------------------------
1305
1306RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1307{
1308 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1309 return dst;
1310}
1311
1312// ------------------------------ DebuggerStatementNode ---------------------------
1313
1314RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1315{
1316 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1317 return dst;
1318}
1319
1320// ------------------------------ ExprStatementNode ----------------------------
1321
1322RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1323{
1324 ASSERT(m_expr);
1325 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1326 return generator.emitNode(dst, m_expr);
1327}
1328
1329// ------------------------------ VarStatementNode ----------------------------
1330
1331RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1332{
1333 ASSERT(m_expr);
1334 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1335 return generator.emitNode(m_expr);
1336}
1337
1338// ------------------------------ IfNode ---------------------------------------
1339
1340RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1341{
1342 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1343
1344 RefPtr<Label> afterThen = generator.newLabel();
1345
1346 RegisterID* cond = generator.emitNode(m_condition);
1347 generator.emitJumpIfFalse(cond, afterThen.get());
1348
1349 generator.emitNode(dst, m_ifBlock);
1350 generator.emitLabel(afterThen.get());
1351
1352 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1353 return 0;
1354}
1355
1356// ------------------------------ IfElseNode ---------------------------------------
1357
1358RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1359{
1360 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1361
1362 RefPtr<Label> beforeElse = generator.newLabel();
1363 RefPtr<Label> afterElse = generator.newLabel();
1364
1365 RegisterID* cond = generator.emitNode(m_condition);
1366 generator.emitJumpIfFalse(cond, beforeElse.get());
1367
1368 generator.emitNode(dst, m_ifBlock);
1369 generator.emitJump(afterElse.get());
1370
1371 generator.emitLabel(beforeElse.get());
1372
1373 generator.emitNode(dst, m_elseBlock);
1374
1375 generator.emitLabel(afterElse.get());
1376
1377 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1378 return 0;
1379}
1380
1381// ------------------------------ DoWhileNode ----------------------------------
1382
1383RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1384{
1385 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1386
1387 RefPtr<Label> topOfLoop = generator.newLabel();
1388 generator.emitLabel(topOfLoop.get());
1389
1390 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1391
1392 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
1393
1394 generator.emitLabel(scope->continueTarget());
1395 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1396 RegisterID* cond = generator.emitNode(m_expr);
1397 generator.emitJumpIfTrue(cond, topOfLoop.get());
1398
1399 generator.emitLabel(scope->breakTarget());
1400 return result.get();
1401}
1402
1403// ------------------------------ WhileNode ------------------------------------
1404
1405RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1406{
1407 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1408
1409 generator.emitJump(scope->continueTarget());
1410
1411 RefPtr<Label> topOfLoop = generator.newLabel();
1412 generator.emitLabel(topOfLoop.get());
1413
1414 generator.emitNode(dst, m_statement);
1415
1416 generator.emitLabel(scope->continueTarget());
1417 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1418 RegisterID* cond = generator.emitNode(m_expr);
1419 generator.emitJumpIfTrue(cond, topOfLoop.get());
1420
1421 generator.emitLabel(scope->breakTarget());
1422
1423 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1424 return 0;
1425}
1426
1427// ------------------------------ ForNode --------------------------------------
1428
1429RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1430{
1431 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1432
1433 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1434
1435 if (m_expr1)
1436 generator.emitNode(generator.ignoredResult(), m_expr1);
1437
1438 RefPtr<Label> condition = generator.newLabel();
1439 generator.emitJump(condition.get());
1440
1441 RefPtr<Label> topOfLoop = generator.newLabel();
1442 generator.emitLabel(topOfLoop.get());
1443
1444 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
1445
1446 generator.emitLabel(scope->continueTarget());
1447 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1448 if (m_expr3)
1449 generator.emitNode(generator.ignoredResult(), m_expr3);
1450
1451 generator.emitLabel(condition.get());
1452 if (m_expr2) {
1453 RegisterID* cond = generator.emitNode(m_expr2);
1454 generator.emitJumpIfTrue(cond, topOfLoop.get());
1455 } else
1456 generator.emitJump(topOfLoop.get());
1457
1458 generator.emitLabel(scope->breakTarget());
1459 return result.get();
1460}
1461
1462// ------------------------------ ForInNode ------------------------------------
1463
1464RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1465{
1466 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1467
1468 if (!m_lexpr->isLocation())
1469 return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
1470
1471 RefPtr<Label> continueTarget = generator.newLabel();
1472
1473 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1474
1475 if (m_init)
1476 generator.emitNode(generator.ignoredResult(), m_init);
1477 RegisterID* forInBase = generator.emitNode(m_expr);
1478 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1479 generator.emitJump(scope->continueTarget());
1480
1481 RefPtr<Label> loopStart = generator.newLabel();
1482 generator.emitLabel(loopStart.get());
1483
1484 RegisterID* propertyName;
1485 if (m_lexpr->isResolveNode()) {
1486 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1487 propertyName = generator.registerFor(ident);
1488 if (!propertyName) {
1489 propertyName = generator.newTemporary();
1490 RefPtr<RegisterID> protect = propertyName;
1491 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1492
1493 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1494 generator.emitPutById(base, ident, propertyName);
1495 }
1496 } else if (m_lexpr->isDotAccessorNode()) {
1497 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1498 const Identifier& ident = assignNode->identifier();
1499 propertyName = generator.newTemporary();
1500 RefPtr<RegisterID> protect = propertyName;
1501 RegisterID* base = generator.emitNode(assignNode->base());
1502
1503 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1504 generator.emitPutById(base, ident, propertyName);
1505 } else {
1506 ASSERT(m_lexpr->isBracketAccessorNode());
1507 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1508 propertyName = generator.newTemporary();
1509 RefPtr<RegisterID> protect = propertyName;
1510 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1511 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1512
1513 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1514 generator.emitPutByVal(base.get(), subscript, propertyName);
1515 }
1516
1517 generator.emitNode(dst, m_statement);
1518
1519 generator.emitLabel(scope->continueTarget());
1520 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1521 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1522 generator.emitLabel(scope->breakTarget());
1523 return dst;
1524}
1525
1526// ------------------------------ ContinueNode ---------------------------------
1527
1528// ECMA 12.7
1529RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1530{
1531 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1532
1533 LabelScope* scope = generator.continueTarget(m_ident);
1534
1535 if (!scope)
1536 return m_ident.isEmpty()
1537 ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
1538 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1539
1540 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
1541 return dst;
1542}
1543
1544// ------------------------------ BreakNode ------------------------------------
1545
1546// ECMA 12.8
1547RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1548{
1549 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1550
1551 LabelScope* scope = generator.breakTarget(m_ident);
1552
1553 if (!scope)
1554 return m_ident.isEmpty()
1555 ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
1556 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1557
1558 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
1559 return dst;
1560}
1561
1562// ------------------------------ ReturnNode -----------------------------------
1563
1564RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1565{
1566 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1567 if (generator.codeType() != FunctionCode)
1568 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
1569
1570 if (dst == generator.ignoredResult())
1571 dst = 0;
1572 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
1573 RefPtr<RegisterID> returnRegister;
1574 if (generator.scopeDepth()) {
1575 RefPtr<Label> l0 = generator.newLabel();
1576 if (generator.hasFinaliser() && !r0->isTemporary()) {
1577 returnRegister = generator.emitMove(generator.newTemporary(), r0);
1578 r0 = returnRegister.get();
1579 }
1580 generator.emitJumpScopes(l0.get(), 0);
1581 generator.emitLabel(l0.get());
1582 }
1583 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1584 return generator.emitReturn(r0);
1585}
1586
1587// ------------------------------ WithNode -------------------------------------
1588
1589RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1590{
1591 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1592
1593 RefPtr<RegisterID> scope = generator.newTemporary();
1594 generator.emitNode(scope.get(), m_expr); // scope must be protected until popped
1595 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
1596 generator.emitPushScope(scope.get());
1597 RegisterID* result = generator.emitNode(dst, m_statement);
1598 generator.emitPopScope();
1599 return result;
1600}
1601
1602// ------------------------------ CaseClauseNode --------------------------------
1603
1604inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1605{
1606 if (m_statements)
1607 m_statements->emitBytecode(generator, dst);
1608}
1609
1610// ------------------------------ CaseBlockNode --------------------------------
1611
1612enum SwitchKind {
1613 SwitchUnset = 0,
1614 SwitchNumber = 1,
1615 SwitchString = 2,
1616 SwitchNeither = 3
1617};
1618
1619static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
1620{
1621 for (; list; list = list->getNext()) {
1622 ExpressionNode* clauseExpression = list->getClause()->expr();
1623 literalVector.append(clauseExpression);
1624 if (clauseExpression->isNumber()) {
1625 double value = static_cast<NumberNode*>(clauseExpression)->value();
1626 int32_t intVal = static_cast<int32_t>(value);
1627 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
1628 typeForTable = SwitchNeither;
1629 break;
1630 }
1631 if (intVal < min_num)
1632 min_num = intVal;
1633 if (intVal > max_num)
1634 max_num = intVal;
1635 typeForTable = SwitchNumber;
1636 continue;
1637 }
1638 if (clauseExpression->isString()) {
1639 if (typeForTable & ~SwitchString) {
1640 typeForTable = SwitchNeither;
1641 break;
1642 }
1643 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
1644 if (singleCharacterSwitch &= value.size() == 1) {
1645 int32_t intVal = value.rep()->data()[0];
1646 if (intVal < min_num)
1647 min_num = intVal;
1648 if (intVal > max_num)
1649 max_num = intVal;
1650 }
1651 typeForTable = SwitchString;
1652 continue;
1653 }
1654 typeForTable = SwitchNeither;
1655 break;
1656 }
1657}
1658
1659SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
1660{
1661 SwitchKind typeForTable = SwitchUnset;
1662 bool singleCharacterSwitch = true;
1663
1664 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1665 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1666
1667 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
1668 return SwitchInfo::SwitchNone;
1669
1670 if (typeForTable == SwitchNumber) {
1671 int32_t range = max_num - min_num;
1672 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1673 return SwitchInfo::SwitchImmediate;
1674 return SwitchInfo::SwitchNone;
1675 }
1676
1677 ASSERT(typeForTable == SwitchString);
1678
1679 if (singleCharacterSwitch) {
1680 int32_t range = max_num - min_num;
1681 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1682 return SwitchInfo::SwitchCharacter;
1683 }
1684
1685 return SwitchInfo::SwitchString;
1686}
1687
1688RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1689{
1690 RefPtr<Label> defaultLabel;
1691 Vector<RefPtr<Label>, 8> labelVector;
1692 Vector<ExpressionNode*, 8> literalVector;
1693 int32_t min_num = std::numeric_limits<int32_t>::max();
1694 int32_t max_num = std::numeric_limits<int32_t>::min();
1695 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
1696
1697 if (switchType != SwitchInfo::SwitchNone) {
1698 // Prepare the various labels
1699 for (uint32_t i = 0; i < literalVector.size(); i++)
1700 labelVector.append(generator.newLabel());
1701 defaultLabel = generator.newLabel();
1702 generator.beginSwitch(switchExpression, switchType);
1703 } else {
1704 // Setup jumps
1705 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1706 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1707 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1708 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1709 labelVector.append(generator.newLabel());
1710 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1711 }
1712
1713 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1714 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1715 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1716 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1717 labelVector.append(generator.newLabel());
1718 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1719 }
1720 defaultLabel = generator.newLabel();
1721 generator.emitJump(defaultLabel.get());
1722 }
1723
1724 RegisterID* result = 0;
1725
1726 size_t i = 0;
1727 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1728 generator.emitLabel(labelVector[i++].get());
1729 list->getClause()->emitBytecode(generator, dst);
1730 }
1731
1732 if (m_defaultClause) {
1733 generator.emitLabel(defaultLabel.get());
1734 m_defaultClause->emitBytecode(generator, dst);
1735 }
1736
1737 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1738 generator.emitLabel(labelVector[i++].get());
1739 list->getClause()->emitBytecode(generator, dst);
1740 }
1741 if (!m_defaultClause)
1742 generator.emitLabel(defaultLabel.get());
1743
1744 ASSERT(i == labelVector.size());
1745 if (switchType != SwitchInfo::SwitchNone) {
1746 ASSERT(labelVector.size() == literalVector.size());
1747 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
1748 }
1749 return result;
1750}
1751
1752// ------------------------------ SwitchNode -----------------------------------
1753
1754RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1755{
1756 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1757
1758 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
1759
1760 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1761 RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
1762
1763 generator.emitLabel(scope->breakTarget());
1764 return r1;
1765}
1766
1767// ------------------------------ LabelNode ------------------------------------
1768
1769RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1770{
1771 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1772
1773 if (generator.breakTarget(m_name))
1774 return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
1775
1776 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
1777 RegisterID* r0 = generator.emitNode(dst, m_statement);
1778
1779 generator.emitLabel(scope->breakTarget());
1780 return r0;
1781}
1782
1783// ------------------------------ ThrowNode ------------------------------------
1784
1785RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1786{
1787 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1788
1789 if (dst == generator.ignoredResult())
1790 dst = 0;
1791 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
1792 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1793 generator.emitThrow(expr.get());
1794 return 0;
1795}
1796
1797// ------------------------------ TryNode --------------------------------------
1798
1799RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1800{
1801 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1802 // optimizer knows they may be jumped to from anywhere.
1803
1804 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1805
1806 RefPtr<Label> tryStartLabel = generator.newLabel();
1807 RefPtr<Label> finallyStart;
1808 RefPtr<RegisterID> finallyReturnAddr;
1809 if (m_finallyBlock) {
1810 finallyStart = generator.newLabel();
1811 finallyReturnAddr = generator.newTemporary();
1812 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
1813 }
1814
1815 generator.emitLabel(tryStartLabel.get());
1816 generator.emitNode(dst, m_tryBlock);
1817
1818 if (m_catchBlock) {
1819 RefPtr<Label> catchEndLabel = generator.newLabel();
1820
1821 // Normal path: jump over the catch block.
1822 generator.emitJump(catchEndLabel.get());
1823
1824 // Uncaught exception path: the catch block.
1825 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
1826 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
1827 if (m_catchHasEval) {
1828 RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
1829 generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
1830 generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
1831 generator.emitPushScope(exceptionRegister.get());
1832 } else
1833 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
1834 generator.emitNode(dst, m_catchBlock);
1835 generator.emitPopScope();
1836 generator.emitLabel(catchEndLabel.get());
1837 }
1838
1839 if (m_finallyBlock) {
1840 generator.popFinallyContext();
1841 // there may be important registers live at the time we jump
1842 // to a finally block (such as for a return or throw) so we
1843 // ref the highest register ever used as a conservative
1844 // approach to not clobbering anything important
1845 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
1846 RefPtr<Label> finallyEndLabel = generator.newLabel();
1847
1848 // Normal path: invoke the finally block, then jump over it.
1849 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1850 generator.emitJump(finallyEndLabel.get());
1851
1852 // Uncaught exception path: invoke the finally block, then re-throw the exception.
1853 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
1854 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
1855 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1856 generator.emitThrow(tempExceptionRegister.get());
1857
1858 // The finally block.
1859 generator.emitLabel(finallyStart.get());
1860 generator.emitNode(dst, m_finallyBlock);
1861 generator.emitSubroutineReturn(finallyReturnAddr.get());
1862
1863 generator.emitLabel(finallyEndLabel.get());
1864 }
1865
1866 return dst;
1867}
1868
1869// -----------------------------ScopeNodeData ---------------------------
1870
1871ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants)
1872 : m_numConstants(numConstants)
1873 , m_statements(statements)
1874{
1875 m_arena.swap(arena);
1876 if (varStack)
1877 m_varStack.swap(*varStack);
1878 if (funcStack)
1879 m_functionStack.swap(*funcStack);
1880}
1881
1882// ------------------------------ ScopeNode -----------------------------
1883
1884ScopeNode::ScopeNode(JSGlobalData* globalData)
1885 : StatementNode(globalData)
1886 , ParserArenaRefCounted(globalData)
1887 , m_features(NoFeatures)
1888{
1889#if ENABLE(CODEBLOCK_SAMPLING)
1890 if (SamplingTool* sampler = globalData->interpreter->sampler())
1891 sampler->notifyOfScope(this);
1892#endif
1893}
1894
1895ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
1896 : StatementNode(globalData)
1897 , ParserArenaRefCounted(globalData)
1898 , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants))
1899 , m_features(features)
1900 , m_source(source)
1901{
1902#if ENABLE(CODEBLOCK_SAMPLING)
1903 if (SamplingTool* sampler = globalData->interpreter->sampler())
1904 sampler->notifyOfScope(this);
1905#endif
1906}
1907
1908inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
1909{
1910 if (m_data->m_statements)
1911 m_data->m_statements->emitBytecode(generator, dst);
1912}
1913
1914StatementNode* ScopeNode::singleStatement() const
1915{
1916 return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
1917}
1918
1919// ------------------------------ ProgramNode -----------------------------
1920
1921inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1922 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
1923{
1924}
1925
1926PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1927{
1928 RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
1929
1930 ASSERT(node->data()->m_arena.last() == node);
1931 node->data()->m_arena.removeLast();
1932 ASSERT(!node->data()->m_arena.contains(node.get()));
1933
1934 return node.release();
1935}
1936
1937RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1938{
1939 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1940
1941 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1942 generator.emitLoad(dstRegister.get(), jsUndefined());
1943 emitStatementsBytecode(generator, dstRegister.get());
1944
1945 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1946 generator.emitEnd(dstRegister.get());
1947 return 0;
1948}
1949
1950// ------------------------------ EvalNode -----------------------------
1951
1952inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1953 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
1954{
1955}
1956
1957PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1958{
1959 RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
1960
1961 ASSERT(node->data()->m_arena.last() == node);
1962 node->data()->m_arena.removeLast();
1963 ASSERT(!node->data()->m_arena.contains(node.get()));
1964
1965 return node.release();
1966}
1967
1968RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1969{
1970 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1971
1972 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1973 generator.emitLoad(dstRegister.get(), jsUndefined());
1974 emitStatementsBytecode(generator, dstRegister.get());
1975
1976 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1977 generator.emitEnd(dstRegister.get());
1978 return 0;
1979}
1980
1981// ------------------------------ FunctionBodyNode -----------------------------
1982
1983inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
1984 : ScopeNode(globalData)
1985 , m_parameters(0)
1986 , m_parameterCount(0)
1987{
1988}
1989
1990inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
1991 : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
1992 , m_parameters(0)
1993 , m_parameterCount(0)
1994{
1995}
1996
1997FunctionBodyNode::~FunctionBodyNode()
1998{
1999 for (size_t i = 0; i < m_parameterCount; ++i)
2000 m_parameters[i].~Identifier();
2001 fastFree(m_parameters);
2002}
2003
2004void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
2005{
2006 Vector<Identifier> parameters;
2007 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
2008 parameters.append(parameter->ident());
2009 size_t count = parameters.size();
2010
2011 setSource(source);
2012 finishParsing(parameters.releaseBuffer(), count, ident);
2013}
2014
2015void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount, const Identifier& ident)
2016{
2017 ASSERT(!source().isNull());
2018 m_parameters = parameters;
2019 m_parameterCount = parameterCount;
2020 m_ident = ident;
2021}
2022
2023FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
2024{
2025 return new FunctionBodyNode(globalData);
2026}
2027
2028PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2029{
2030 RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
2031
2032 ASSERT(node->data()->m_arena.last() == node);
2033 node->data()->m_arena.removeLast();
2034 ASSERT(!node->data()->m_arena.contains(node.get()));
2035
2036 return node.release();
2037}
2038
2039void FunctionBodyNode::reparseDataIfNecessary(ScopeChainNode* scopeChainNode)
2040{
2041 // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
2042 // calling Parser::parse<FunctionBodyNode>().
2043 if (!data())
2044 scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this);
2045 ASSERT(data());
2046}
2047
2048RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2049{
2050 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2051 emitStatementsBytecode(generator, generator.ignoredResult());
2052 StatementNode* singleStatement = this->singleStatement();
2053 if (singleStatement && singleStatement->isBlock()) {
2054 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2055 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
2056 return 0;
2057 }
2058
2059 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
2060 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2061 generator.emitReturn(r0);
2062 return 0;
2063}
2064
2065UString FunctionBodyNode::paramString() const
2066{
2067 UString s("");
2068 for (size_t pos = 0; pos < m_parameterCount; ++pos) {
2069 if (!s.isEmpty())
2070 s += ", ";
2071 s += parameters()[pos].ustring();
2072 }
2073
2074 return s;
2075}
2076
2077Identifier* FunctionBodyNode::copyParameters()
2078{
2079 Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
2080 VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
2081 return parameters;
2082}
2083
2084// ------------------------------ FuncDeclNode ---------------------------------
2085
2086RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2087{
2088 if (dst == generator.ignoredResult())
2089 dst = 0;
2090 return dst;
2091}
2092
2093// ------------------------------ FuncExprNode ---------------------------------
2094
2095RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2096{
2097 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2098}
2099
2100} // namespace JSC
Note: See TracBrowser for help on using the repository browser.