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

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

Remove AST nodes from use within the Runtime (outside of parsing), stage 1
https://bugs.webkit.org/show_bug.cgi?id=28330

Reviewed by Oliver Hunt.

Remove the EvalNode and ProgramNode from use in the runtime. They still exist
after this patch, but are hidden behind EvalExecutable and FunctionExecutable,
and are also still reachable behind CodeBlock::m_ownerNode.

The next step will be to beat back FunctionBodyNode in the same fashion.
Then remove the usage via CodeBlock, then only construct these nodes only on
demand during bytecode generation.

(JSC::GlobalCodeBlock::GlobalCodeBlock):
(JSC::GlobalCodeBlock::~GlobalCodeBlock):
(JSC::ProgramCodeBlock::ProgramCodeBlock):
(JSC::EvalCodeBlock::EvalCodeBlock):
(JSC::FunctionCodeBlock::FunctionCodeBlock):
(JSC::NativeCodeBlock::NativeCodeBlock):

  • bytecode/EvalCodeCache.h:

(JSC::EvalCodeCache::get):

  • debugger/Debugger.cpp:

(JSC::evaluateInGlobalCallFrame):

  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::evaluate):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::callEval):
(JSC::Interpreter::execute):

  • interpreter/Interpreter.h:
  • parser/Nodes.cpp:

(JSC::FunctionBodyNode::createNativeThunk):
(JSC::FunctionBodyNode::generateBytecode):
(JSC::FunctionBodyNode::bytecodeForExceptionInfoReparse):

  • parser/Parser.h:

(JSC::Parser::parse):
(JSC::Parser::reparse):
(JSC::Parser::parseFunctionFromGlobalCode):
(JSC::::parse):

  • runtime/Completion.cpp:

(JSC::checkSyntax):
(JSC::evaluate):

  • runtime/Error.cpp:

(JSC::throwError):

  • runtime/Error.h:
  • runtime/Executable.h: Added.

(JSC::TemplateExecutable::TemplateExecutable):
(JSC::TemplateExecutable::markAggregate):
(JSC::TemplateExecutable::sourceURL):
(JSC::TemplateExecutable::lineNo):
(JSC::TemplateExecutable::bytecode):
(JSC::TemplateExecutable::jitCode):
(JSC::EvalExecutable::EvalExecutable):
(JSC::ProgramExecutable::ProgramExecutable):

  • runtime/FunctionConstructor.cpp:

(JSC::constructFunction):

  • runtime/FunctionConstructor.h:
  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::numericCompareFunction):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::~JSGlobalObject):
(JSC::JSGlobalObject::markChildren):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::codeBlocks):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncEval):

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