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

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

JavaScriptCore:

2009-05-13 Darin Adler <Darin Adler>

Reviewed by Cameron Zwarich.

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

Step 3: Add some actual arena allocation. About 1% SunSpider speedup.

  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): Updated since VarStack contains const Identifier* now. (JSC::BytecodeGenerator::emitPushNewScope): Updated to take a const Identifier&.
  • bytecompiler/BytecodeGenerator.h: Ditto
  • bytecompiler/SegmentedVector.h: Added isEmpty.
  • debugger/Debugger.cpp: (JSC::Debugger::recompileAllJSFunctions): Moved this function here from WebCore so WebCore doesn't need the details of FunctionBodyNode.
  • debugger/Debugger.h: Ditto.
  • interpreter/Interpreter.cpp: (JSC::Interpreter::execute): Updated since VarStack contains const Identifier* now.
  • jit/JITStubs.cpp: (JSC::JITStubs::cti_vm_lazyLinkCall): Call isHostFunction on the body rather than on the function object, since we can't easily have inlined access to the FunctionBodyNode in JSFunction.h since WebCore needs access to that header. (JSC::JITStubs::cti_op_construct_JSConstruct): Ditto.
  • profiler/Profiler.cpp: (JSC::Profiler::createCallIdentifier): Ditto.
  • parser/Grammar.y: Use JSGlobalData* to pass the global data pointer around whenever possible instead of using void*. Changed SET_EXCEPTION_LOCATION from a macro to an inline function. Marked the structure-creating functions inline. Changed the VarStack to use identifier pointers instead of actual identifiers. This takes advantage of the fact that all identifier pointers come from the arena and avoids referenc count churn. Changed Identifier* to const Identifier* to make sure we don't modify any by accident. Used identifiers for regular expression strings too, using the new scanRegExp that has out parameters instead of the old one that relied on side effects in the Lexer. Move the creation of numeric identifiers out of this file and into the PropertyNode constructor.
  • 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::scanRegExp): Added out arguments that are const Identifier* as well as a prefix character argument so we can handle the /= case without a string append. (JSC::Lexer::skipRegExp): Added. Skips a regular expression without allocating Identifier objects. (JSC::Lexer::clear): Removed the code to manage m_identifiers, m_pattern, and m_flags, 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::RegExpNode::RegExpNode): Changed arguments to Identifier instead of UString since these come from the parser which makes identifiers. (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): Updated since the pattern and flags are now Identifier instead of UString. Also 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::EvalNode::generateBytecode): Removed code to clear the children vector. This optimization is no longer possible since everything is in a single arena. (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 th 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.
  • 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 the segmented vector of identifiers that used to be in the Lexer.
  • runtime/FunctionConstructor.cpp: (JSC::extractFunctionBody): Use singleStatement function rather than getting at a StatementVector.
  • runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): Call isHostFunction on the body rather than the function object.
  • runtime/JSFunction.cpp: (JSC::JSFunction::JSFunction): Moved the structure version of this in here from the header. It's not hot enough that it needs to be inlined. (JSC::JSFunction::isHostFunction): Moved this in here from the header. It's now a helper to be used only within the class. (JSC::JSFunction::setBody): Moved this in here. It's not hot enough that it needs to be inlined, and we want to be able to compile the header without the definition of FunctionBodyNode.
  • runtime/JSFunction.h: Eliminated the include of "Nodes.h". This was exposing too much JavaScriptCore dependency to WebCore. Because of this change and some changes made to WebCore, we could now export a lot fewer headers from JavaScriptCore, but I have not done that yet in this check-in. Made a couple functions non-inline. Removes some isHostFunction() assertions.


  • wtf/FastAllocBase.h: Added the conventional using statements we use in WTF so we can use identifiers from the WTF namespace without explicit namespace qualification or namespace directive. This is the usual WTF style, although it's unconventional in the C++ world. We use the namespace primarily for link-time disambiguation, not compile-time.
  • wtf/FastMalloc.cpp: Fixed an incorrect comment.

WebCore:

2009-05-13 Darin Adler <Darin Adler>

Reviewed by Cameron Zwarich.

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

  • bindings/js/JSDOMBinding.h: Removed include of JSFunction.h. We don't want the entire DOM binding to depend on that file.
  • bindings/js/JSAudioConstructor.cpp: Added include of Error.h. Before we inherited this automatically because JDDOMBinding.h included JSFunction.h, but that was excessive.
  • bindings/js/JSDOMWindowCustom.cpp: Ditto.
  • bindings/js/JSHTMLInputElementCustom.cpp: Ditto.
  • bindings/js/JSImageConstructor.cpp: Ditto.
  • bindings/js/JSLazyEventListener.cpp: Ditto, but for JSFunction.h.
  • bindings/js/JSMessageChannelConstructor.cpp: Ditto.
  • bindings/js/JSOptionConstructor.cpp: Ditto.
  • bindings/js/JSWorkerConstructor.cpp: Ditto.
  • bindings/js/JSXMLHttpRequestConstructor.cpp: Ditto.
  • bridge/jni/jni_jsobject.mm: Ditto, but for SourceCode.h.
  • inspector/InspectorController.cpp: Ditto.
  • inspector/JavaScriptDebugServer.cpp: (WebCore::JavaScriptDebugServer::recompileAllJSFunctions): Moved mose of this function into the base class in JavaScriptCore, so the details of compilation don't have to be exposed.

WebKit/mac:

2009-05-13 Darin Adler <Darin Adler>

Reviewed by Cameron Zwarich.

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

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm: Updated includes. New ones needed due to reducing includes of JSDOMBinding.h.
  • WebView/WebScriptDebugger.mm: Ditto.
  • Property svn:eol-style set to native
File size: 91.7 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_double);
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.emitResolveFunction(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> base = generator.emitNode(m_base);
417 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
418 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
419 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
420 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
421}
422
423RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
424{
425 RefPtr<Label> realCall = generator.newLabel();
426 RefPtr<Label> end = generator.newLabel();
427 RefPtr<RegisterID> base = generator.emitNode(m_base);
428 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
429 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
430 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
431 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
432 {
433 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
434 RefPtr<RegisterID> thisRegister = generator.newTemporary();
435 ArgumentListNode* oldList = m_args->m_listNode;
436 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
437 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
438 m_args->m_listNode = m_args->m_listNode->m_next;
439 } else
440 generator.emitLoad(thisRegister.get(), jsNull());
441
442 generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
443 generator.emitJump(end.get());
444 m_args->m_listNode = oldList;
445 }
446 generator.emitLabel(realCall.get());
447 {
448 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
449 generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
450 }
451 generator.emitLabel(end.get());
452 return finalDestination.get();
453}
454
455static bool areTrivialApplyArguments(ArgumentsNode* args)
456{
457 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
458 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
459}
460
461RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
462{
463 // A few simple cases can be trivially handled as ordinary function calls.
464 // function.apply(), function.apply(arg) -> identical to function.call
465 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
466 bool mayBeCall = areTrivialApplyArguments(m_args);
467
468 RefPtr<Label> realCall = generator.newLabel();
469 RefPtr<Label> end = generator.newLabel();
470 RefPtr<RegisterID> base = generator.emitNode(m_base);
471 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
472 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
473 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
474 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
475 {
476 if (mayBeCall) {
477 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
478 RefPtr<RegisterID> thisRegister = generator.newTemporary();
479 ArgumentListNode* oldList = m_args->m_listNode;
480 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
481 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
482 m_args->m_listNode = m_args->m_listNode->m_next;
483 if (m_args->m_listNode) {
484 ASSERT(m_args->m_listNode->m_expr->isSimpleArray());
485 ASSERT(!m_args->m_listNode->m_next);
486 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData());
487 }
488 } else
489 generator.emitLoad(thisRegister.get(), jsNull());
490 generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
491 m_args->m_listNode = oldList;
492 } else {
493 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
494 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
495 RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
496 RefPtr<RegisterID> thisRegister = generator.newTemporary();
497 RefPtr<RegisterID> argsRegister = generator.newTemporary();
498 generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
499 ArgumentListNode* args = m_args->m_listNode->m_next;
500 bool isArgumentsApply = false;
501 if (args->m_expr->isResolveNode()) {
502 ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr);
503 isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier());
504 if (isArgumentsApply)
505 generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments());
506 }
507 if (!isArgumentsApply)
508 generator.emitNode(argsRegister.get(), args->m_expr);
509 while ((args = args->m_next))
510 generator.emitNode(args->m_expr);
511
512 generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
513 generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
514 }
515 generator.emitJump(end.get());
516 }
517 generator.emitLabel(realCall.get());
518 {
519 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
520 generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
521 }
522 generator.emitLabel(end.get());
523 return finalDestination.get();
524}
525
526// ------------------------------ PostfixResolveNode ----------------------------------
527
528static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
529{
530 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
531}
532
533static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
534{
535 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
536}
537
538RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
539{
540 if (RegisterID* local = generator.registerFor(m_ident)) {
541 if (generator.isLocalConstant(m_ident)) {
542 if (dst == generator.ignoredResult())
543 return 0;
544 return generator.emitToJSNumber(generator.finalDestination(dst), local);
545 }
546
547 if (dst == generator.ignoredResult())
548 return emitPreIncOrDec(generator, local, m_operator);
549 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
550 }
551
552 int index = 0;
553 size_t depth = 0;
554 JSObject* globalObject = 0;
555 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
556 RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
557 RegisterID* oldValue;
558 if (dst == generator.ignoredResult()) {
559 oldValue = 0;
560 emitPreIncOrDec(generator, value.get(), m_operator);
561 } else {
562 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
563 }
564 generator.emitPutScopedVar(depth, index, value.get(), globalObject);
565 return oldValue;
566 }
567
568 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
569 RefPtr<RegisterID> value = generator.newTemporary();
570 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
571 RegisterID* oldValue;
572 if (dst == generator.ignoredResult()) {
573 oldValue = 0;
574 emitPreIncOrDec(generator, value.get(), m_operator);
575 } else {
576 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
577 }
578 generator.emitPutById(base.get(), m_ident, value.get());
579 return oldValue;
580}
581
582// ------------------------------ PostfixBracketNode ----------------------------------
583
584RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
585{
586 RefPtr<RegisterID> base = generator.emitNode(m_base);
587 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
588
589 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
590 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
591 RegisterID* oldValue;
592 if (dst == generator.ignoredResult()) {
593 oldValue = 0;
594 if (m_operator == OpPlusPlus)
595 generator.emitPreInc(value.get());
596 else
597 generator.emitPreDec(value.get());
598 } else {
599 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
600 }
601 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
602 generator.emitPutByVal(base.get(), property.get(), value.get());
603 return oldValue;
604}
605
606// ------------------------------ PostfixDotNode ----------------------------------
607
608RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
609{
610 RefPtr<RegisterID> base = generator.emitNode(m_base);
611
612 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
613 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
614 RegisterID* oldValue;
615 if (dst == generator.ignoredResult()) {
616 oldValue = 0;
617 if (m_operator == OpPlusPlus)
618 generator.emitPreInc(value.get());
619 else
620 generator.emitPreDec(value.get());
621 } else {
622 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
623 }
624 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
625 generator.emitPutById(base.get(), m_ident, value.get());
626 return oldValue;
627}
628
629// ------------------------------ PostfixErrorNode -----------------------------------
630
631RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
632{
633 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
634 ? "Postfix ++ operator applied to value that is not a reference."
635 : "Postfix -- operator applied to value that is not a reference.");
636}
637
638// ------------------------------ DeleteResolveNode -----------------------------------
639
640RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
641{
642 if (generator.registerFor(m_ident))
643 return generator.emitUnexpectedLoad(generator.finalDestination(dst), false);
644
645 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
646 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
647 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
648}
649
650// ------------------------------ DeleteBracketNode -----------------------------------
651
652RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
653{
654 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
655 RegisterID* r1 = generator.emitNode(m_subscript);
656
657 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
658 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
659}
660
661// ------------------------------ DeleteDotNode -----------------------------------
662
663RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
664{
665 RegisterID* r0 = generator.emitNode(m_base);
666
667 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
668 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
669}
670
671// ------------------------------ DeleteValueNode -----------------------------------
672
673RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
674{
675 generator.emitNode(generator.ignoredResult(), m_expr);
676
677 // delete on a non-location expression ignores the value and returns true
678 return generator.emitUnexpectedLoad(generator.finalDestination(dst), true);
679}
680
681// ------------------------------ VoidNode -------------------------------------
682
683RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
684{
685 if (dst == generator.ignoredResult()) {
686 generator.emitNode(generator.ignoredResult(), m_expr);
687 return 0;
688 }
689 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
690 return generator.emitLoad(dst, jsUndefined());
691}
692
693// ------------------------------ TypeOfValueNode -----------------------------------
694
695RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
696{
697 if (RegisterID* local = generator.registerFor(m_ident)) {
698 if (dst == generator.ignoredResult())
699 return 0;
700 return generator.emitTypeOf(generator.finalDestination(dst), local);
701 }
702
703 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
704 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
705 if (dst == generator.ignoredResult())
706 return 0;
707 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
708}
709
710// ------------------------------ TypeOfValueNode -----------------------------------
711
712RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
713{
714 if (dst == generator.ignoredResult()) {
715 generator.emitNode(generator.ignoredResult(), m_expr);
716 return 0;
717 }
718 RefPtr<RegisterID> src = generator.emitNode(m_expr);
719 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
720}
721
722// ------------------------------ PrefixResolveNode ----------------------------------
723
724RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
725{
726 if (RegisterID* local = generator.registerFor(m_ident)) {
727 if (generator.isLocalConstant(m_ident)) {
728 if (dst == generator.ignoredResult())
729 return 0;
730 RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
731 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
732 }
733
734 emitPreIncOrDec(generator, local, m_operator);
735 return generator.moveToDestinationIfNeeded(dst, local);
736 }
737
738 int index = 0;
739 size_t depth = 0;
740 JSObject* globalObject = 0;
741 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
742 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
743 emitPreIncOrDec(generator, propDst.get(), m_operator);
744 generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
745 return generator.moveToDestinationIfNeeded(dst, propDst.get());
746 }
747
748 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
749 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
750 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
751 emitPreIncOrDec(generator, propDst.get(), m_operator);
752 generator.emitPutById(base.get(), m_ident, propDst.get());
753 return generator.moveToDestinationIfNeeded(dst, propDst.get());
754}
755
756// ------------------------------ PrefixBracketNode ----------------------------------
757
758RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
759{
760 RefPtr<RegisterID> base = generator.emitNode(m_base);
761 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
762 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
763
764 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
765 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
766 if (m_operator == OpPlusPlus)
767 generator.emitPreInc(value);
768 else
769 generator.emitPreDec(value);
770 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
771 generator.emitPutByVal(base.get(), property.get(), value);
772 return generator.moveToDestinationIfNeeded(dst, propDst.get());
773}
774
775// ------------------------------ PrefixDotNode ----------------------------------
776
777RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
778{
779 RefPtr<RegisterID> base = generator.emitNode(m_base);
780 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
781
782 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
783 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
784 if (m_operator == OpPlusPlus)
785 generator.emitPreInc(value);
786 else
787 generator.emitPreDec(value);
788 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
789 generator.emitPutById(base.get(), m_ident, value);
790 return generator.moveToDestinationIfNeeded(dst, propDst.get());
791}
792
793// ------------------------------ PrefixErrorNode -----------------------------------
794
795RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
796{
797 return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
798 ? "Prefix ++ operator applied to value that is not a reference."
799 : "Prefix -- operator applied to value that is not a reference.");
800}
801
802// ------------------------------ Unary Operation Nodes -----------------------------------
803
804RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
805{
806 RegisterID* src = generator.emitNode(m_expr);
807 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
808}
809
810// ------------------------------ Binary Operation Nodes -----------------------------------
811
812// BinaryOpNode::emitStrcat:
813//
814// This node generates an op_strcat operation. This opcode can handle concatenation of three or
815// more values, where we can determine a set of separate op_add operations would be operating on
816// string values.
817//
818// This function expects to be operating on a graph of AST nodes looking something like this:
819//
820// (a)... (b)
821// \ /
822// (+) (c)
823// \ /
824// [d] ((+))
825// \ /
826// [+=]
827//
828// The assignment operation is optional, if it exists the register holding the value on the
829// lefthand side of the assignment should be passing as the optional 'lhs' argument.
830//
831// The method should be called on the node at the root of the tree of regular binary add
832// operations (marked in the diagram with a double set of parentheses). This node must
833// be performing a string concatenation (determined by statically detecting that at least
834// one child must be a string).
835//
836// Since the minimum number of values being concatenated together is expected to be 3, if
837// a lhs to a concatenating assignment is not provided then the root add should have at
838// least one left child that is also an add that can be determined to be operating on strings.
839//
840RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
841{
842 ASSERT(isAdd());
843 ASSERT(resultDescriptor().definitelyIsString());
844
845 // Create a list of expressions for all the adds in the tree of nodes we can convert into
846 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
847 // added first, and the leftmost child is never added, so the vector produced for the
848 // example above will be [ c, b ].
849 Vector<ExpressionNode*, 16> reverseExpressionList;
850 reverseExpressionList.append(m_expr2);
851
852 // Examine the left child of the add. So long as this is a string add, add its right-child
853 // to the list, and keep processing along the left fork.
854 ExpressionNode* leftMostAddChild = m_expr1;
855 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
856 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
857 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
858 }
859
860 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
861
862 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
863 // We could possibly avoid this (the lhs is converted last anyway, we could let the
864 // op_strcat node handle its conversion if required).
865 if (lhs)
866 temporaryRegisters.append(generator.newTemporary());
867
868 // Emit code for the leftmost node ((a) in the example).
869 temporaryRegisters.append(generator.newTemporary());
870 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
871 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
872
873 // Note on ordering of conversions:
874 //
875 // We maintain the same ordering of conversions as we would see if the concatenations
876 // was performed as a sequence of adds (otherwise this optimization could change
877 // behaviour should an object have been provided a valueOf or toString method).
878 //
879 // Considering the above example, the sequnce of execution is:
880 // * evaluate operand (a)
881 // * evaluate operand (b)
882 // * convert (a) to primitive <- (this would be triggered by the first add)
883 // * convert (b) to primitive <- (ditto)
884 // * evaluate operand (c)
885 // * convert (c) to primitive <- (this would be triggered by the second add)
886 // And optionally, if there is an assignment:
887 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
888 //
889 // As such we do not plant an op to convert the leftmost child now. Instead, use
890 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
891 // once the second node has been generated. However, if the leftmost child is an
892 // immediate we can trivially determine that no conversion will be required.
893 // If this is the case
894 if (leftMostAddChild->isString())
895 leftMostAddChildTempRegister = 0;
896
897 while (reverseExpressionList.size()) {
898 ExpressionNode* node = reverseExpressionList.last();
899 reverseExpressionList.removeLast();
900
901 // Emit the code for the current node.
902 temporaryRegisters.append(generator.newTemporary());
903 generator.emitNode(temporaryRegisters.last().get(), node);
904
905 // On the first iteration of this loop, when we first reach this point we have just
906 // generated the second node, which means it is time to convert the leftmost operand.
907 if (leftMostAddChildTempRegister) {
908 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
909 leftMostAddChildTempRegister = 0; // Only do this once.
910 }
911 // Plant a conversion for this node, if necessary.
912 if (!node->isString())
913 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
914 }
915 ASSERT(temporaryRegisters.size() >= 3);
916
917 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
918 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
919 if (emitExpressionInfoForMe)
920 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
921
922 // If there is an assignment convert the lhs now. This will also copy lhs to
923 // the temporary register we allocated for it.
924 if (lhs)
925 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
926
927 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
928}
929
930RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
931{
932 OpcodeID opcodeID = this->opcodeID();
933
934 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString())
935 return emitStrcat(generator, dst);
936
937 if (opcodeID == op_neq) {
938 if (m_expr1->isNull() || m_expr2->isNull()) {
939 RefPtr<RegisterID> src = generator.tempDestination(dst);
940 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
941 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
942 }
943 }
944
945 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
946 RegisterID* src2 = generator.emitNode(m_expr2);
947 return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
948}
949
950RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
951{
952 if (m_expr1->isNull() || m_expr2->isNull()) {
953 RefPtr<RegisterID> src = generator.tempDestination(dst);
954 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
955 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
956 }
957
958 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
959 RegisterID* src2 = generator.emitNode(m_expr2);
960 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
961}
962
963RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
964{
965 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
966 RegisterID* src2 = generator.emitNode(m_expr2);
967 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
968}
969
970RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
971{
972 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
973 RegisterID* src2 = generator.emitNode(m_expr2);
974 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
975}
976
977RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
978{
979 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
980 RegisterID* src2 = generator.emitNode(m_expr2);
981 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
982 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
983}
984
985RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
986{
987 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
988 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
989
990 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
991 generator.emitGetByIdExceptionInfo(op_instanceof);
992 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
993
994 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
995 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
996}
997
998// ------------------------------ LogicalOpNode ----------------------------
999
1000RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1001{
1002 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1003 RefPtr<Label> target = generator.newLabel();
1004
1005 generator.emitNode(temp.get(), m_expr1);
1006 if (m_operator == OpLogicalAnd)
1007 generator.emitJumpIfFalse(temp.get(), target.get());
1008 else
1009 generator.emitJumpIfTrue(temp.get(), target.get());
1010 generator.emitNode(temp.get(), m_expr2);
1011 generator.emitLabel(target.get());
1012
1013 return generator.moveToDestinationIfNeeded(dst, temp.get());
1014}
1015
1016// ------------------------------ ConditionalNode ------------------------------
1017
1018RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1019{
1020 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1021 RefPtr<Label> beforeElse = generator.newLabel();
1022 RefPtr<Label> afterElse = generator.newLabel();
1023
1024 RegisterID* cond = generator.emitNode(m_logical);
1025 generator.emitJumpIfFalse(cond, beforeElse.get());
1026
1027 generator.emitNode(newDst.get(), m_expr1);
1028 generator.emitJump(afterElse.get());
1029
1030 generator.emitLabel(beforeElse.get());
1031 generator.emitNode(newDst.get(), m_expr2);
1032
1033 generator.emitLabel(afterElse.get());
1034
1035 return newDst.get();
1036}
1037
1038// ------------------------------ ReadModifyResolveNode -----------------------------------
1039
1040// FIXME: should this be moved to be a method on BytecodeGenerator?
1041static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1042{
1043 OpcodeID opcodeID;
1044 switch (oper) {
1045 case OpMultEq:
1046 opcodeID = op_mul;
1047 break;
1048 case OpDivEq:
1049 opcodeID = op_div;
1050 break;
1051 case OpPlusEq:
1052 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1053 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1054 opcodeID = op_add;
1055 break;
1056 case OpMinusEq:
1057 opcodeID = op_sub;
1058 break;
1059 case OpLShift:
1060 opcodeID = op_lshift;
1061 break;
1062 case OpRShift:
1063 opcodeID = op_rshift;
1064 break;
1065 case OpURShift:
1066 opcodeID = op_urshift;
1067 break;
1068 case OpAndEq:
1069 opcodeID = op_bitand;
1070 break;
1071 case OpXOrEq:
1072 opcodeID = op_bitxor;
1073 break;
1074 case OpOrEq:
1075 opcodeID = op_bitor;
1076 break;
1077 case OpModEq:
1078 opcodeID = op_mod;
1079 break;
1080 default:
1081 ASSERT_NOT_REACHED();
1082 return dst;
1083 }
1084
1085 RegisterID* src2 = generator.emitNode(m_right);
1086
1087 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1088 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1089 if (emitExpressionInfoForMe)
1090 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
1091
1092 return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1093}
1094
1095RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1096{
1097 if (RegisterID* local = generator.registerFor(m_ident)) {
1098 if (generator.isLocalConstant(m_ident)) {
1099 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1100 }
1101
1102 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1103 RefPtr<RegisterID> result = generator.newTemporary();
1104 generator.emitMove(result.get(), local);
1105 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1106 generator.emitMove(local, result.get());
1107 return generator.moveToDestinationIfNeeded(dst, result.get());
1108 }
1109
1110 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1111 return generator.moveToDestinationIfNeeded(dst, result);
1112 }
1113
1114 int index = 0;
1115 size_t depth = 0;
1116 JSObject* globalObject = 0;
1117 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1118 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
1119 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1120 generator.emitPutScopedVar(depth, index, result, globalObject);
1121 return result;
1122 }
1123
1124 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
1125 generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
1126 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
1127 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
1128 return generator.emitPutById(base.get(), m_ident, result);
1129}
1130
1131// ------------------------------ AssignResolveNode -----------------------------------
1132
1133RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1134{
1135 if (RegisterID* local = generator.registerFor(m_ident)) {
1136 if (generator.isLocalConstant(m_ident))
1137 return generator.emitNode(dst, m_right);
1138
1139 RegisterID* result = generator.emitNode(local, m_right);
1140 return generator.moveToDestinationIfNeeded(dst, result);
1141 }
1142
1143 int index = 0;
1144 size_t depth = 0;
1145 JSObject* globalObject = 0;
1146 if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
1147 if (dst == generator.ignoredResult())
1148 dst = 0;
1149 RegisterID* value = generator.emitNode(dst, m_right);
1150 generator.emitPutScopedVar(depth, index, value, globalObject);
1151 return value;
1152 }
1153
1154 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1155 if (dst == generator.ignoredResult())
1156 dst = 0;
1157 RegisterID* value = generator.emitNode(dst, m_right);
1158 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1159 return generator.emitPutById(base.get(), m_ident, value);
1160}
1161
1162// ------------------------------ AssignDotNode -----------------------------------
1163
1164RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1165{
1166 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1167 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1168 RegisterID* result = generator.emitNode(value.get(), m_right);
1169 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1170 generator.emitPutById(base.get(), m_ident, result);
1171 return generator.moveToDestinationIfNeeded(dst, result);
1172}
1173
1174// ------------------------------ ReadModifyDotNode -----------------------------------
1175
1176RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1177{
1178 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1179
1180 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1181 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1182 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1183
1184 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1185 return generator.emitPutById(base.get(), m_ident, updatedValue);
1186}
1187
1188// ------------------------------ AssignErrorNode -----------------------------------
1189
1190RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1191{
1192 return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
1193}
1194
1195// ------------------------------ AssignBracketNode -----------------------------------
1196
1197RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1198{
1199 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1200 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1201 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1202 RegisterID* result = generator.emitNode(value.get(), m_right);
1203
1204 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1205 generator.emitPutByVal(base.get(), property.get(), result);
1206 return generator.moveToDestinationIfNeeded(dst, result);
1207}
1208
1209// ------------------------------ ReadModifyBracketNode -----------------------------------
1210
1211RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1212{
1213 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1214 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1215
1216 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1217 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1218 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1219
1220 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1221 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1222
1223 return updatedValue;
1224}
1225
1226// ------------------------------ CommaNode ------------------------------------
1227
1228RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1229{
1230 generator.emitNode(generator.ignoredResult(), m_expr1);
1231 return generator.emitNode(dst, m_expr2);
1232}
1233
1234// ------------------------------ ConstDeclNode ------------------------------------
1235
1236RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1237{
1238 if (RegisterID* local = generator.constRegisterFor(m_ident)) {
1239 if (!m_init)
1240 return local;
1241
1242 return generator.emitNode(local, m_init);
1243 }
1244
1245 // FIXME: While this code should only be hit in eval code, it will potentially
1246 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1247 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
1248 RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1249 return generator.emitPutById(base.get(), m_ident, value);
1250}
1251
1252RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1253{
1254 RegisterID* result = 0;
1255 for (ConstDeclNode* n = this; n; n = n->m_next)
1256 result = n->emitCodeSingle(generator);
1257
1258 return result;
1259}
1260
1261// ------------------------------ ConstStatementNode -----------------------------
1262
1263RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1264{
1265 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1266 return generator.emitNode(m_next);
1267}
1268
1269// ------------------------------ SourceElements -------------------------------
1270
1271inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1272{
1273 size_t size = m_statements.size();
1274 for (size_t i = 0; i < size; ++i)
1275 generator.emitNode(dst, m_statements[i]);
1276}
1277
1278// ------------------------------ BlockNode ------------------------------------
1279
1280inline StatementNode* BlockNode::lastStatement() const
1281{
1282 return m_statements ? m_statements->lastStatement() : 0;
1283}
1284
1285RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1286{
1287 if (m_statements)
1288 m_statements->emitBytecode(generator, dst);
1289 return 0;
1290}
1291
1292// ------------------------------ EmptyStatementNode ---------------------------
1293
1294RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1295{
1296 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1297 return dst;
1298}
1299
1300// ------------------------------ DebuggerStatementNode ---------------------------
1301
1302RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1303{
1304 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1305 return dst;
1306}
1307
1308// ------------------------------ ExprStatementNode ----------------------------
1309
1310RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1311{
1312 ASSERT(m_expr);
1313 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1314 return generator.emitNode(dst, m_expr);
1315}
1316
1317// ------------------------------ VarStatementNode ----------------------------
1318
1319RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1320{
1321 ASSERT(m_expr);
1322 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1323 return generator.emitNode(m_expr);
1324}
1325
1326// ------------------------------ IfNode ---------------------------------------
1327
1328RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1329{
1330 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1331
1332 RefPtr<Label> afterThen = generator.newLabel();
1333
1334 RegisterID* cond = generator.emitNode(m_condition);
1335 generator.emitJumpIfFalse(cond, afterThen.get());
1336
1337 generator.emitNode(dst, m_ifBlock);
1338 generator.emitLabel(afterThen.get());
1339
1340 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1341 return 0;
1342}
1343
1344// ------------------------------ IfElseNode ---------------------------------------
1345
1346RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1347{
1348 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1349
1350 RefPtr<Label> beforeElse = generator.newLabel();
1351 RefPtr<Label> afterElse = generator.newLabel();
1352
1353 RegisterID* cond = generator.emitNode(m_condition);
1354 generator.emitJumpIfFalse(cond, beforeElse.get());
1355
1356 generator.emitNode(dst, m_ifBlock);
1357 generator.emitJump(afterElse.get());
1358
1359 generator.emitLabel(beforeElse.get());
1360
1361 generator.emitNode(dst, m_elseBlock);
1362
1363 generator.emitLabel(afterElse.get());
1364
1365 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1366 return 0;
1367}
1368
1369// ------------------------------ DoWhileNode ----------------------------------
1370
1371RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1372{
1373 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1374
1375 RefPtr<Label> topOfLoop = generator.newLabel();
1376 generator.emitLabel(topOfLoop.get());
1377
1378 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1379
1380 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
1381
1382 generator.emitLabel(scope->continueTarget());
1383 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1384 RegisterID* cond = generator.emitNode(m_expr);
1385 generator.emitJumpIfTrue(cond, topOfLoop.get());
1386
1387 generator.emitLabel(scope->breakTarget());
1388 return result.get();
1389}
1390
1391// ------------------------------ WhileNode ------------------------------------
1392
1393RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1394{
1395 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1396
1397 generator.emitJump(scope->continueTarget());
1398
1399 RefPtr<Label> topOfLoop = generator.newLabel();
1400 generator.emitLabel(topOfLoop.get());
1401
1402 generator.emitNode(dst, m_statement);
1403
1404 generator.emitLabel(scope->continueTarget());
1405 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1406 RegisterID* cond = generator.emitNode(m_expr);
1407 generator.emitJumpIfTrue(cond, topOfLoop.get());
1408
1409 generator.emitLabel(scope->breakTarget());
1410
1411 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1412 return 0;
1413}
1414
1415// ------------------------------ ForNode --------------------------------------
1416
1417RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1418{
1419 if (dst == generator.ignoredResult())
1420 dst = 0;
1421
1422 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1423
1424 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1425
1426 if (m_expr1)
1427 generator.emitNode(generator.ignoredResult(), m_expr1);
1428
1429 RefPtr<Label> condition = generator.newLabel();
1430 generator.emitJump(condition.get());
1431
1432 RefPtr<Label> topOfLoop = generator.newLabel();
1433 generator.emitLabel(topOfLoop.get());
1434
1435 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
1436
1437 generator.emitLabel(scope->continueTarget());
1438 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1439 if (m_expr3)
1440 generator.emitNode(generator.ignoredResult(), m_expr3);
1441
1442 generator.emitLabel(condition.get());
1443 if (m_expr2) {
1444 RegisterID* cond = generator.emitNode(m_expr2);
1445 generator.emitJumpIfTrue(cond, topOfLoop.get());
1446 } else
1447 generator.emitJump(topOfLoop.get());
1448
1449 generator.emitLabel(scope->breakTarget());
1450 return result.get();
1451}
1452
1453// ------------------------------ ForInNode ------------------------------------
1454
1455RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1456{
1457 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1458
1459 if (!m_lexpr->isLocation())
1460 return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
1461
1462 RefPtr<Label> continueTarget = generator.newLabel();
1463
1464 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1465
1466 if (m_init)
1467 generator.emitNode(generator.ignoredResult(), m_init);
1468 RegisterID* forInBase = generator.emitNode(m_expr);
1469 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase);
1470 generator.emitJump(scope->continueTarget());
1471
1472 RefPtr<Label> loopStart = generator.newLabel();
1473 generator.emitLabel(loopStart.get());
1474
1475 RegisterID* propertyName;
1476 if (m_lexpr->isResolveNode()) {
1477 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1478 propertyName = generator.registerFor(ident);
1479 if (!propertyName) {
1480 propertyName = generator.newTemporary();
1481 RefPtr<RegisterID> protect = propertyName;
1482 RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
1483
1484 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1485 generator.emitPutById(base, ident, propertyName);
1486 }
1487 } else if (m_lexpr->isDotAccessorNode()) {
1488 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1489 const Identifier& ident = assignNode->identifier();
1490 propertyName = generator.newTemporary();
1491 RefPtr<RegisterID> protect = propertyName;
1492 RegisterID* base = generator.emitNode(assignNode->base());
1493
1494 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1495 generator.emitPutById(base, ident, propertyName);
1496 } else {
1497 ASSERT(m_lexpr->isBracketAccessorNode());
1498 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1499 propertyName = generator.newTemporary();
1500 RefPtr<RegisterID> protect = propertyName;
1501 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1502 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1503
1504 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1505 generator.emitPutByVal(base.get(), subscript, propertyName);
1506 }
1507
1508 generator.emitNode(dst, m_statement);
1509
1510 generator.emitLabel(scope->continueTarget());
1511 generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get());
1512 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1513 generator.emitLabel(scope->breakTarget());
1514 return dst;
1515}
1516
1517// ------------------------------ ContinueNode ---------------------------------
1518
1519// ECMA 12.7
1520RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1521{
1522 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1523
1524 LabelScope* scope = generator.continueTarget(m_ident);
1525
1526 if (!scope)
1527 return m_ident.isEmpty()
1528 ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
1529 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1530
1531 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
1532 return dst;
1533}
1534
1535// ------------------------------ BreakNode ------------------------------------
1536
1537// ECMA 12.8
1538RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1539{
1540 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1541
1542 LabelScope* scope = generator.breakTarget(m_ident);
1543
1544 if (!scope)
1545 return m_ident.isEmpty()
1546 ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
1547 : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
1548
1549 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
1550 return dst;
1551}
1552
1553// ------------------------------ ReturnNode -----------------------------------
1554
1555RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1556{
1557 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1558 if (generator.codeType() != FunctionCode)
1559 return emitThrowError(generator, SyntaxError, "Invalid return statement.");
1560
1561 if (dst == generator.ignoredResult())
1562 dst = 0;
1563 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
1564 RefPtr<RegisterID> returnRegister;
1565 if (generator.scopeDepth()) {
1566 RefPtr<Label> l0 = generator.newLabel();
1567 if (generator.hasFinaliser() && !r0->isTemporary()) {
1568 returnRegister = generator.emitMove(generator.newTemporary(), r0);
1569 r0 = returnRegister.get();
1570 }
1571 generator.emitJumpScopes(l0.get(), 0);
1572 generator.emitLabel(l0.get());
1573 }
1574 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1575 return generator.emitReturn(r0);
1576}
1577
1578// ------------------------------ WithNode -------------------------------------
1579
1580RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1581{
1582 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1583
1584 RefPtr<RegisterID> scope = generator.newTemporary();
1585 generator.emitNode(scope.get(), m_expr); // scope must be protected until popped
1586 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
1587 generator.emitPushScope(scope.get());
1588 RegisterID* result = generator.emitNode(dst, m_statement);
1589 generator.emitPopScope();
1590 return result;
1591}
1592
1593// ------------------------------ CaseClauseNode --------------------------------
1594
1595inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1596{
1597 if (m_statements)
1598 m_statements->emitBytecode(generator, dst);
1599}
1600
1601// ------------------------------ CaseBlockNode --------------------------------
1602
1603enum SwitchKind {
1604 SwitchUnset = 0,
1605 SwitchNumber = 1,
1606 SwitchString = 2,
1607 SwitchNeither = 3
1608};
1609
1610static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
1611{
1612 for (; list; list = list->getNext()) {
1613 ExpressionNode* clauseExpression = list->getClause()->expr();
1614 literalVector.append(clauseExpression);
1615 if (clauseExpression->isNumber()) {
1616 double value = static_cast<NumberNode*>(clauseExpression)->value();
1617 JSValue jsValue = JSValue::makeInt32Fast(static_cast<int32_t>(value));
1618 if ((typeForTable & ~SwitchNumber) || !jsValue || (jsValue.getInt32Fast() != value)) {
1619 typeForTable = SwitchNeither;
1620 break;
1621 }
1622 int32_t intVal = static_cast<int32_t>(value);
1623 ASSERT(intVal == value);
1624 if (intVal < min_num)
1625 min_num = intVal;
1626 if (intVal > max_num)
1627 max_num = intVal;
1628 typeForTable = SwitchNumber;
1629 continue;
1630 }
1631 if (clauseExpression->isString()) {
1632 if (typeForTable & ~SwitchString) {
1633 typeForTable = SwitchNeither;
1634 break;
1635 }
1636 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
1637 if (singleCharacterSwitch &= value.size() == 1) {
1638 int32_t intVal = value.rep()->data()[0];
1639 if (intVal < min_num)
1640 min_num = intVal;
1641 if (intVal > max_num)
1642 max_num = intVal;
1643 }
1644 typeForTable = SwitchString;
1645 continue;
1646 }
1647 typeForTable = SwitchNeither;
1648 break;
1649 }
1650}
1651
1652SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
1653{
1654 SwitchKind typeForTable = SwitchUnset;
1655 bool singleCharacterSwitch = true;
1656
1657 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1658 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1659
1660 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
1661 return SwitchInfo::SwitchNone;
1662
1663 if (typeForTable == SwitchNumber) {
1664 int32_t range = max_num - min_num;
1665 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1666 return SwitchInfo::SwitchImmediate;
1667 return SwitchInfo::SwitchNone;
1668 }
1669
1670 ASSERT(typeForTable == SwitchString);
1671
1672 if (singleCharacterSwitch) {
1673 int32_t range = max_num - min_num;
1674 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1675 return SwitchInfo::SwitchCharacter;
1676 }
1677
1678 return SwitchInfo::SwitchString;
1679}
1680
1681RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1682{
1683 RefPtr<Label> defaultLabel;
1684 Vector<RefPtr<Label>, 8> labelVector;
1685 Vector<ExpressionNode*, 8> literalVector;
1686 int32_t min_num = std::numeric_limits<int32_t>::max();
1687 int32_t max_num = std::numeric_limits<int32_t>::min();
1688 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
1689
1690 if (switchType != SwitchInfo::SwitchNone) {
1691 // Prepare the various labels
1692 for (uint32_t i = 0; i < literalVector.size(); i++)
1693 labelVector.append(generator.newLabel());
1694 defaultLabel = generator.newLabel();
1695 generator.beginSwitch(switchExpression, switchType);
1696 } else {
1697 // Setup jumps
1698 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1699 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1700 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1701 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1702 labelVector.append(generator.newLabel());
1703 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1704 }
1705
1706 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1707 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1708 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1709 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1710 labelVector.append(generator.newLabel());
1711 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1712 }
1713 defaultLabel = generator.newLabel();
1714 generator.emitJump(defaultLabel.get());
1715 }
1716
1717 RegisterID* result = 0;
1718
1719 size_t i = 0;
1720 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1721 generator.emitLabel(labelVector[i++].get());
1722 list->getClause()->emitBytecode(generator, dst);
1723 }
1724
1725 if (m_defaultClause) {
1726 generator.emitLabel(defaultLabel.get());
1727 m_defaultClause->emitBytecode(generator, dst);
1728 }
1729
1730 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1731 generator.emitLabel(labelVector[i++].get());
1732 list->getClause()->emitBytecode(generator, dst);
1733 }
1734 if (!m_defaultClause)
1735 generator.emitLabel(defaultLabel.get());
1736
1737 ASSERT(i == labelVector.size());
1738 if (switchType != SwitchInfo::SwitchNone) {
1739 ASSERT(labelVector.size() == literalVector.size());
1740 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
1741 }
1742 return result;
1743}
1744
1745// ------------------------------ SwitchNode -----------------------------------
1746
1747RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1748{
1749 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1750
1751 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
1752
1753 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1754 RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
1755
1756 generator.emitLabel(scope->breakTarget());
1757 return r1;
1758}
1759
1760// ------------------------------ LabelNode ------------------------------------
1761
1762RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1763{
1764 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1765
1766 if (generator.breakTarget(m_name))
1767 return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
1768
1769 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
1770 RegisterID* r0 = generator.emitNode(dst, m_statement);
1771
1772 generator.emitLabel(scope->breakTarget());
1773 return r0;
1774}
1775
1776// ------------------------------ ThrowNode ------------------------------------
1777
1778RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1779{
1780 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1781
1782 if (dst == generator.ignoredResult())
1783 dst = 0;
1784 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
1785 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1786 generator.emitThrow(expr.get());
1787 return 0;
1788}
1789
1790// ------------------------------ TryNode --------------------------------------
1791
1792RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1793{
1794 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1795
1796 RefPtr<Label> tryStartLabel = generator.newLabel();
1797 RefPtr<Label> tryEndLabel = generator.newLabel();
1798 RefPtr<Label> finallyStart;
1799 RefPtr<RegisterID> finallyReturnAddr;
1800 if (m_finallyBlock) {
1801 finallyStart = generator.newLabel();
1802 finallyReturnAddr = generator.newTemporary();
1803 generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
1804 }
1805 generator.emitLabel(tryStartLabel.get());
1806 generator.emitNode(dst, m_tryBlock);
1807 generator.emitLabel(tryEndLabel.get());
1808
1809 if (m_catchBlock) {
1810 RefPtr<Label> handlerEndLabel = generator.newLabel();
1811 generator.emitJump(handlerEndLabel.get());
1812 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get());
1813 if (m_catchHasEval) {
1814 RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary());
1815 generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get());
1816 generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get());
1817 generator.emitPushScope(exceptionRegister.get());
1818 } else
1819 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
1820 generator.emitNode(dst, m_catchBlock);
1821 generator.emitPopScope();
1822 generator.emitLabel(handlerEndLabel.get());
1823 }
1824
1825 if (m_finallyBlock) {
1826 generator.popFinallyContext();
1827 // there may be important registers live at the time we jump
1828 // to a finally block (such as for a return or throw) so we
1829 // ref the highest register ever used as a conservative
1830 // approach to not clobbering anything important
1831 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
1832 RefPtr<Label> finallyEndLabel = generator.newLabel();
1833 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1834 // Use a label to record the subtle fact that sret will return to the
1835 // next instruction. sret is the only way to jump without an explicit label.
1836 generator.emitLabel(generator.newLabel().get());
1837 generator.emitJump(finallyEndLabel.get());
1838
1839 // Finally block for exception path
1840 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get());
1841 generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
1842 // Use a label to record the subtle fact that sret will return to the
1843 // next instruction. sret is the only way to jump without an explicit label.
1844 generator.emitLabel(generator.newLabel().get());
1845 generator.emitThrow(tempExceptionRegister.get());
1846
1847 // emit the finally block itself
1848 generator.emitLabel(finallyStart.get());
1849 generator.emitNode(dst, m_finallyBlock);
1850 generator.emitSubroutineReturn(finallyReturnAddr.get());
1851
1852 generator.emitLabel(finallyEndLabel.get());
1853 }
1854
1855 return dst;
1856}
1857
1858// -----------------------------ScopeNodeData ---------------------------
1859
1860ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants)
1861 : m_numConstants(numConstants)
1862 , m_statements(statements)
1863{
1864 m_arena.swap(arena);
1865 if (varStack)
1866 m_varStack.swap(*varStack);
1867 if (funcStack)
1868 m_functionStack.swap(*funcStack);
1869}
1870
1871void ScopeNodeData::mark()
1872{
1873 FunctionStack::iterator end = m_functionStack.end();
1874 for (FunctionStack::iterator ptr = m_functionStack.begin(); ptr != end; ++ptr) {
1875 FunctionBodyNode* body = (*ptr)->body();
1876 if (!body->isGenerated())
1877 continue;
1878 body->generatedBytecode().mark();
1879 }
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
1914inline StatementNode* 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
1950void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode)
1951{
1952 ScopeChain scopeChain(scopeChainNode);
1953 JSGlobalObject* globalObject = scopeChain.globalObject();
1954
1955 m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
1956
1957 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get());
1958 generator.generate();
1959
1960 destroyData();
1961}
1962
1963// ------------------------------ EvalNode -----------------------------
1964
1965inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1966 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
1967{
1968}
1969
1970PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
1971{
1972 RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
1973
1974 ASSERT(node->data()->m_arena.last() == node);
1975 node->data()->m_arena.removeLast();
1976 ASSERT(!node->data()->m_arena.contains(node.get()));
1977
1978 return node.release();
1979}
1980
1981RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1982{
1983 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
1984
1985 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1986 generator.emitLoad(dstRegister.get(), jsUndefined());
1987 emitStatementsBytecode(generator, dstRegister.get());
1988
1989 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
1990 generator.emitEnd(dstRegister.get());
1991 return 0;
1992}
1993
1994void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode)
1995{
1996 ScopeChain scopeChain(scopeChainNode);
1997 JSGlobalObject* globalObject = scopeChain.globalObject();
1998
1999 m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
2000
2001 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
2002 generator.generate();
2003
2004 // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
2005 // so the ScopeNodeData cannot be destroyed at this point. Maybe we can destroy part of it in the future?
2006}
2007
2008EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
2009{
2010 ASSERT(!m_code);
2011
2012 ScopeChain scopeChain(scopeChainNode);
2013 JSGlobalObject* globalObject = scopeChain.globalObject();
2014
2015 m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
2016
2017 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
2018 generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
2019 generator.generate();
2020
2021 return *m_code;
2022}
2023
2024void EvalNode::mark()
2025{
2026 // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that
2027 data()->mark();
2028}
2029
2030// ------------------------------ FunctionBodyNode -----------------------------
2031
2032inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
2033 : ScopeNode(globalData)
2034#if ENABLE(JIT)
2035 , m_jitCode(0)
2036#endif
2037 , m_parameters(0)
2038 , m_parameterCount(0)
2039{
2040}
2041
2042inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2043 : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
2044#if ENABLE(JIT)
2045 , m_jitCode(0)
2046#endif
2047 , m_parameters(0)
2048 , m_parameterCount(0)
2049{
2050}
2051
2052FunctionBodyNode::~FunctionBodyNode()
2053{
2054 for (size_t i = 0; i < m_parameterCount; ++i)
2055 m_parameters[i].~Identifier();
2056 fastFree(m_parameters);
2057}
2058
2059void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter)
2060{
2061 Vector<Identifier> parameters;
2062 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
2063 parameters.append(parameter->ident());
2064 size_t count = parameters.size();
2065
2066 setSource(source);
2067 finishParsing(parameters.releaseBuffer(), count);
2068}
2069
2070void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount)
2071{
2072 ASSERT(!source().isNull());
2073 m_parameters = parameters;
2074 m_parameterCount = parameterCount;
2075}
2076
2077void FunctionBodyNode::mark()
2078{
2079 if (m_code)
2080 m_code->mark();
2081}
2082
2083#if ENABLE(JIT)
2084PassRefPtr<FunctionBodyNode> FunctionBodyNode::createNativeThunk(JSGlobalData* globalData)
2085{
2086 RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData);
2087 globalData->parser->arena().reset();
2088 body->m_jitCode = globalData->jitStubs.ctiNativeCallThunk();
2089 return body.release();
2090}
2091#endif
2092
2093FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
2094{
2095 return new FunctionBodyNode(globalData);
2096}
2097
2098PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
2099{
2100 RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
2101
2102 ASSERT(node->data()->m_arena.last() == node);
2103 node->data()->m_arena.removeLast();
2104 ASSERT(!node->data()->m_arena.contains(node.get()));
2105
2106 return node.release();
2107}
2108
2109void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode)
2110{
2111 // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
2112 // calling Parser::parse<FunctionBodyNode>().
2113 if (!data())
2114 scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this);
2115 ASSERT(data());
2116
2117 ScopeChain scopeChain(scopeChainNode);
2118 JSGlobalObject* globalObject = scopeChain.globalObject();
2119
2120 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
2121
2122 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
2123 generator.generate();
2124
2125 destroyData();
2126}
2127
2128#if ENABLE(JIT)
2129void FunctionBodyNode::generateJITCode(ScopeChainNode* scopeChainNode)
2130{
2131 bytecode(scopeChainNode);
2132 ASSERT(m_code);
2133 ASSERT(!m_code->jitCode());
2134 JIT::compile(scopeChainNode->globalData, m_code.get());
2135 ASSERT(m_code->jitCode());
2136 m_jitCode = m_code->jitCode();
2137}
2138#endif
2139
2140CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom)
2141{
2142 ASSERT(!m_code);
2143
2144 ScopeChain scopeChain(scopeChainNode);
2145 JSGlobalObject* globalObject = scopeChain.globalObject();
2146
2147 m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
2148
2149 BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get());
2150 generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom);
2151 generator.generate();
2152
2153 return *m_code;
2154}
2155
2156RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2157{
2158 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2159 emitStatementsBytecode(generator, generator.ignoredResult());
2160 StatementNode* singleStatement = this->singleStatement();
2161 if (singleStatement && singleStatement->isBlock()) {
2162 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2163 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
2164 return 0;
2165 }
2166
2167 RegisterID* r0 = generator.emitLoad(0, jsUndefined());
2168 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2169 generator.emitReturn(r0);
2170 return 0;
2171}
2172
2173UString FunctionBodyNode::paramString() const
2174{
2175 UString s("");
2176 for (size_t pos = 0; pos < m_parameterCount; ++pos) {
2177 if (!s.isEmpty())
2178 s += ", ";
2179 s += parameters()[pos].ustring();
2180 }
2181
2182 return s;
2183}
2184
2185Identifier* FunctionBodyNode::copyParameters()
2186{
2187 Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier)));
2188 VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters);
2189 return parameters;
2190}
2191
2192// ------------------------------ FuncDeclNode ---------------------------------
2193
2194JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2195{
2196 return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2197}
2198
2199RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2200{
2201 if (dst == generator.ignoredResult())
2202 dst = 0;
2203 return dst;
2204}
2205
2206// ------------------------------ FuncExprNode ---------------------------------
2207
2208RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2209{
2210 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2211}
2212
2213JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain)
2214{
2215 JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain);
2216
2217 /*
2218 The Identifier in a FunctionExpression can be referenced from inside
2219 the FunctionExpression's FunctionBody to allow the function to call
2220 itself recursively. However, unlike in a FunctionDeclaration, the
2221 Identifier in a FunctionExpression cannot be referenced from and
2222 does not affect the scope enclosing the FunctionExpression.
2223 */
2224
2225 if (!m_ident.isNull()) {
2226 JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete);
2227 func->scope().push(functionScopeObject);
2228 }
2229
2230 return func;
2231}
2232
2233} // namespace JSC
Note: See TracBrowser for help on using the repository browser.