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

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

2009-05-10 Darin Adler <Darin Adler>

Reviewed by Sam Weinig.

Bug 25674: syntax tree nodes should use arena allocation
Part one: Change lifetimes so we won't have to use reference
counting so much, but don't eliminate the reference counts
entirely yet.

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