2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6 * Copyright (C) 2007 Maks Orlovich
7 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
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.
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.
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.
28 #include "NodeConstructors.h"
30 #include "BytecodeGenerator.h"
31 #include "CallFrame.h"
34 #include "JSFunction.h"
35 #include "JSGlobalObject.h"
36 #include "JSStaticScopeObject.h"
37 #include "LabelScope.h"
39 #include "Operations.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>
52 static void substitute(UString
& string
, const UString
& substring
);
54 // ------------------------------ ThrowableExpressionData --------------------------------
56 static void substitute(UString
& string
, const UString
& substring
)
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));
66 RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType e
, const char* msg
)
68 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
69 RegisterID
* exception
= generator
.emitNewError(generator
.newTemporary(), e
, jsString(generator
.globalData(), msg
));
70 generator
.emitThrow(exception
);
74 RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType e
, const char* msg
, const Identifier
& label
)
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
);
84 // ------------------------------ StatementNode --------------------------------
86 void StatementNode::setLoc(int firstLine
, int lastLine
)
89 m_lastLine
= lastLine
;
92 // ------------------------------ SourceElements --------------------------------
94 void SourceElements::append(StatementNode
* statement
)
96 if (statement
->isEmptyStatement())
98 m_statements
.append(statement
);
101 // ------------------------------ NullNode -------------------------------------
103 RegisterID
* NullNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
105 if (dst
== generator
.ignoredResult())
107 return generator
.emitLoad(dst
, jsNull());
110 // ------------------------------ BooleanNode ----------------------------------
112 RegisterID
* BooleanNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
114 if (dst
== generator
.ignoredResult())
116 return generator
.emitLoad(dst
, m_value
);
119 // ------------------------------ NumberNode -----------------------------------
121 RegisterID
* NumberNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
123 if (dst
== generator
.ignoredResult())
125 return generator
.emitLoad(dst
, m_double
);
128 // ------------------------------ StringNode -----------------------------------
130 RegisterID
* StringNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
132 if (dst
== generator
.ignoredResult())
134 return generator
.emitLoad(dst
, m_value
);
137 // ------------------------------ RegExpNode -----------------------------------
139 RegisterID
* RegExpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
141 RefPtr
<RegExp
> regExp
= RegExp::create(generator
.globalData(), m_pattern
, m_flags
);
142 if (!regExp
->isValid())
143 return emitThrowError(generator
, SyntaxError
, ("Invalid regular expression: " + UString(regExp
->errorMessage())).UTF8String().c_str());
144 if (dst
== generator
.ignoredResult())
146 return generator
.emitNewRegExp(generator
.finalDestination(dst
), regExp
.get());
149 // ------------------------------ ThisNode -------------------------------------
151 RegisterID
* ThisNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
153 if (dst
== generator
.ignoredResult())
155 return generator
.moveToDestinationIfNeeded(dst
, generator
.thisRegister());
158 // ------------------------------ ResolveNode ----------------------------------
160 bool ResolveNode::isPure(BytecodeGenerator
& generator
) const
162 return generator
.isLocal(m_ident
);
165 RegisterID
* ResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
167 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
168 if (dst
== generator
.ignoredResult())
170 return generator
.moveToDestinationIfNeeded(dst
, local
);
173 generator
.emitExpressionInfo(m_startOffset
+ m_ident
.size(), m_ident
.size(), 0);
174 return generator
.emitResolve(generator
.finalDestination(dst
), m_ident
);
177 // ------------------------------ ArrayNode ------------------------------------
179 RegisterID
* ArrayNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
181 // FIXME: Should we put all of this code into emitNewArray?
184 ElementNode
* firstPutElement
;
185 for (firstPutElement
= m_element
; firstPutElement
; firstPutElement
= firstPutElement
->next()) {
186 if (firstPutElement
->elision())
191 if (!firstPutElement
&& !m_elision
)
192 return generator
.emitNewArray(generator
.finalDestination(dst
), m_element
);
194 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.tempDestination(dst
), m_element
);
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
);
203 RegisterID
* value
= generator
.emitLoad(0, jsNumber(generator
.globalData(), m_elision
+ length
));
204 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, value
);
207 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
210 bool ArrayNode::isSimpleArray() const
212 if (m_elision
|| m_optional
)
214 for (ElementNode
* ptr
= m_element
; ptr
; ptr
= ptr
->next()) {
221 ArgumentListNode
* ArrayNode::toArgumentList(JSGlobalData
* globalData
) const
223 ASSERT(!m_elision
&& !m_optional
);
224 ElementNode
* ptr
= m_element
;
227 ArgumentListNode
* head
= new (globalData
) ArgumentListNode(globalData
, ptr
->value());
228 ArgumentListNode
* tail
= head
;
230 for (; ptr
; ptr
= ptr
->next()) {
231 ASSERT(!ptr
->elision());
232 tail
= new (globalData
) ArgumentListNode(globalData
, tail
, ptr
->value());
237 // ------------------------------ ObjectLiteralNode ----------------------------
239 RegisterID
* ObjectLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
242 if (dst
== generator
.ignoredResult())
244 return generator
.emitNewObject(generator
.finalDestination(dst
));
246 return generator
.emitNode(dst
, m_list
);
249 // ------------------------------ PropertyListNode -----------------------------
251 RegisterID
* PropertyListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
253 RefPtr
<RegisterID
> newObj
= generator
.tempDestination(dst
);
255 generator
.emitNewObject(newObj
.get());
257 for (PropertyListNode
* p
= this; p
; p
= p
->m_next
) {
258 RegisterID
* value
= generator
.emitNode(p
->m_node
->m_assign
);
260 switch (p
->m_node
->m_type
) {
261 case PropertyNode::Constant
: {
262 generator
.emitPutById(newObj
.get(), p
->m_node
->name(), value
);
265 case PropertyNode::Getter
: {
266 generator
.emitPutGetter(newObj
.get(), p
->m_node
->name(), value
);
269 case PropertyNode::Setter
: {
270 generator
.emitPutSetter(newObj
.get(), p
->m_node
->name(), value
);
274 ASSERT_NOT_REACHED();
278 return generator
.moveToDestinationIfNeeded(dst
, newObj
.get());
281 // ------------------------------ BracketAccessorNode --------------------------------
283 RegisterID
* BracketAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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
);
291 // ------------------------------ DotAccessorNode --------------------------------
293 RegisterID
* DotAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
295 RegisterID
* base
= generator
.emitNode(m_base
);
296 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
297 return generator
.emitGetById(generator
.finalDestination(dst
), base
, m_ident
);
300 // ------------------------------ ArgumentListNode -----------------------------
302 RegisterID
* ArgumentListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
305 return generator
.emitNode(dst
, m_expr
);
308 // ------------------------------ NewExprNode ----------------------------------
310 RegisterID
* NewExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
312 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
313 return generator
.emitConstruct(generator
.finalDestination(dst
), func
.get(), m_args
, divot(), startOffset(), endOffset());
316 // ------------------------------ EvalFunctionCallNode ----------------------------------
318 RegisterID
* EvalFunctionCallNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
327 // ------------------------------ FunctionCallValueNode ----------------------------------
329 RegisterID
* FunctionCallValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
336 // ------------------------------ FunctionCallResolveNode ----------------------------------
338 RegisterID
* FunctionCallResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
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());
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());
362 // ------------------------------ FunctionCallBracketNode ----------------------------------
364 RegisterID
* FunctionCallBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
374 // ------------------------------ FunctionCallDotNode ----------------------------------
376 RegisterID
* FunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
387 RegisterID
* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
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
;
404 generator
.emitLoad(thisRegister
.get(), jsNull());
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
;
410 generator
.emitLabel(realCall
.get());
412 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
413 generator
.emitCall(finalDestination
.get(), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
415 generator
.emitLabel(end
.get());
416 return finalDestination
.get();
419 static bool areTrivialApplyArguments(ArgumentsNode
* args
)
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());
425 RegisterID
* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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
);
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());
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());
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
;
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());
471 if (!isArgumentsApply
)
472 generator
.emitNode(argsRegister
.get(), args
->m_expr
);
473 while ((args
= args
->m_next
))
474 generator
.emitNode(args
->m_expr
);
476 generator
.emitLoadVarargs(argsCountRegister
.get(), argsRegister
.get());
477 generator
.emitCallVarargs(finalDestination
.get(), realFunction
.get(), thisRegister
.get(), argsCountRegister
.get(), divot(), startOffset(), endOffset());
479 generator
.emitJump(end
.get());
481 generator
.emitLabel(realCall
.get());
483 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
484 generator
.emitCall(finalDestination
.get(), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
486 generator
.emitLabel(end
.get());
487 return finalDestination
.get();
490 // ------------------------------ PostfixResolveNode ----------------------------------
492 static RegisterID
* emitPreIncOrDec(BytecodeGenerator
& generator
, RegisterID
* srcDst
, Operator oper
)
494 return (oper
== OpPlusPlus
) ? generator
.emitPreInc(srcDst
) : generator
.emitPreDec(srcDst
);
497 static RegisterID
* emitPostIncOrDec(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* srcDst
, Operator oper
)
500 return generator
.emitToJSNumber(dst
, srcDst
);
501 return (oper
== OpPlusPlus
) ? generator
.emitPostInc(dst
, srcDst
) : generator
.emitPostDec(dst
, srcDst
);
504 RegisterID
* PostfixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
506 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
507 if (generator
.isLocalConstant(m_ident
)) {
508 if (dst
== generator
.ignoredResult())
510 return generator
.emitToJSNumber(generator
.finalDestination(dst
), local
);
513 if (dst
== generator
.ignoredResult())
514 return emitPreIncOrDec(generator
, local
, m_operator
);
515 return emitPostIncOrDec(generator
, generator
.finalDestination(dst
), local
, m_operator
);
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()) {
526 emitPreIncOrDec(generator
, value
.get(), m_operator
);
528 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
530 generator
.emitPutScopedVar(depth
, index
, value
.get(), globalObject
);
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()) {
540 emitPreIncOrDec(generator
, value
.get(), m_operator
);
542 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
544 generator
.emitPutById(base
.get(), m_ident
, value
.get());
548 // ------------------------------ PostfixBracketNode ----------------------------------
550 RegisterID
* PostfixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
552 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
553 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
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()) {
560 if (m_operator
== OpPlusPlus
)
561 generator
.emitPreInc(value
.get());
563 generator
.emitPreDec(value
.get());
565 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
567 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
568 generator
.emitPutByVal(base
.get(), property
.get(), value
.get());
572 // ------------------------------ PostfixDotNode ----------------------------------
574 RegisterID
* PostfixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
576 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
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()) {
583 if (m_operator
== OpPlusPlus
)
584 generator
.emitPreInc(value
.get());
586 generator
.emitPreDec(value
.get());
588 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
590 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
591 generator
.emitPutById(base
.get(), m_ident
, value
.get());
595 // ------------------------------ PostfixErrorNode -----------------------------------
597 RegisterID
* PostfixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
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.");
602 // ------------------------------ DeleteResolveNode -----------------------------------
604 RegisterID
* DeleteResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
606 if (generator
.registerFor(m_ident
))
607 return generator
.emitLoad(generator
.finalDestination(dst
), false);
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
);
614 // ------------------------------ DeleteBracketNode -----------------------------------
616 RegisterID
* DeleteBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
618 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
619 RegisterID
* r1
= generator
.emitNode(m_subscript
);
621 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
622 return generator
.emitDeleteByVal(generator
.finalDestination(dst
), r0
.get(), r1
);
625 // ------------------------------ DeleteDotNode -----------------------------------
627 RegisterID
* DeleteDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
629 RegisterID
* r0
= generator
.emitNode(m_base
);
631 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
632 return generator
.emitDeleteById(generator
.finalDestination(dst
), r0
, m_ident
);
635 // ------------------------------ DeleteValueNode -----------------------------------
637 RegisterID
* DeleteValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
639 generator
.emitNode(generator
.ignoredResult(), m_expr
);
641 // delete on a non-location expression ignores the value and returns true
642 return generator
.emitLoad(generator
.finalDestination(dst
), true);
645 // ------------------------------ VoidNode -------------------------------------
647 RegisterID
* VoidNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
649 if (dst
== generator
.ignoredResult()) {
650 generator
.emitNode(generator
.ignoredResult(), m_expr
);
653 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
654 return generator
.emitLoad(dst
, jsUndefined());
657 // ------------------------------ TypeOfValueNode -----------------------------------
659 RegisterID
* TypeOfResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
661 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
662 if (dst
== generator
.ignoredResult())
664 return generator
.emitTypeOf(generator
.finalDestination(dst
), local
);
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())
671 return generator
.emitTypeOf(generator
.finalDestination(dst
, scratch
.get()), scratch
.get());
674 // ------------------------------ TypeOfValueNode -----------------------------------
676 RegisterID
* TypeOfValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
678 if (dst
== generator
.ignoredResult()) {
679 generator
.emitNode(generator
.ignoredResult(), m_expr
);
682 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
683 return generator
.emitTypeOf(generator
.finalDestination(dst
), src
.get());
686 // ------------------------------ PrefixResolveNode ----------------------------------
688 RegisterID
* PrefixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
690 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
691 if (generator
.isLocalConstant(m_ident
)) {
692 if (dst
== generator
.ignoredResult())
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());
698 emitPreIncOrDec(generator
, local
, m_operator
);
699 return generator
.moveToDestinationIfNeeded(dst
, local
);
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());
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());
720 // ------------------------------ PrefixBracketNode ----------------------------------
722 RegisterID
* PrefixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
724 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
725 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
726 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
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
);
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());
739 // ------------------------------ PrefixDotNode ----------------------------------
741 RegisterID
* PrefixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
743 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
744 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
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
);
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());
757 // ------------------------------ PrefixErrorNode -----------------------------------
759 RegisterID
* PrefixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
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.");
764 // ------------------------------ Unary Operation Nodes -----------------------------------
766 RegisterID
* UnaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
768 RegisterID
* src
= generator
.emitNode(m_expr
);
769 return generator
.emitUnaryOp(opcodeID(), generator
.finalDestination(dst
), src
);
772 // ------------------------------ Binary Operation Nodes -----------------------------------
774 // BinaryOpNode::emitStrcat:
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
780 // This function expects to be operating on a graph of AST nodes looking something like this:
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.
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).
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.
802 RegisterID
* BinaryOpNode::emitStrcat(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* lhs
, ReadModifyResolveNode
* emitExpressionInfoForMe
)
805 ASSERT(resultDescriptor().definitelyIsString());
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
);
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
;
822 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
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).
828 temporaryRegisters
.append(generator
.newTemporary());
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
);
835 // Note on ordering of conversions:
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).
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)
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;
859 while (reverseExpressionList
.size()) {
860 ExpressionNode
* node
= reverseExpressionList
.last();
861 reverseExpressionList
.removeLast();
863 // Emit the code for the current node.
864 temporaryRegisters
.append(generator
.newTemporary());
865 generator
.emitNode(temporaryRegisters
.last().get(), node
);
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.
873 // Plant a conversion for this node, if necessary.
874 if (!node
->isString())
875 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
877 ASSERT(temporaryRegisters
.size() >= 3);
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());
884 // If there is an assignment convert the lhs now. This will also copy lhs to
885 // the temporary register we allocated for it.
887 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
889 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
892 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
894 OpcodeID opcodeID
= this->opcodeID();
896 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString())
897 return emitStrcat(generator
, dst
);
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());
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()));
912 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
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
);
925 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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
);
932 RegisterID
* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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()));
939 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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()));
947 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
949 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
950 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
952 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
953 generator
.emitGetByIdExceptionInfo(op_instanceof
);
954 RegisterID
* src2Prototype
= generator
.emitGetById(generator
.newTemporary(), src2
.get(), generator
.globalData()->propertyNames
->prototype
);
956 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
957 return generator
.emitInstanceOf(generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), src2Prototype
);
960 // ------------------------------ LogicalOpNode ----------------------------
962 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
964 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
965 RefPtr
<Label
> target
= generator
.newLabel();
967 generator
.emitNode(temp
.get(), m_expr1
);
968 if (m_operator
== OpLogicalAnd
)
969 generator
.emitJumpIfFalse(temp
.get(), target
.get());
971 generator
.emitJumpIfTrue(temp
.get(), target
.get());
972 generator
.emitNode(temp
.get(), m_expr2
);
973 generator
.emitLabel(target
.get());
975 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
978 // ------------------------------ ConditionalNode ------------------------------
980 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
982 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
983 RefPtr
<Label
> beforeElse
= generator
.newLabel();
984 RefPtr
<Label
> afterElse
= generator
.newLabel();
986 RegisterID
* cond
= generator
.emitNode(m_logical
);
987 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
989 generator
.emitNode(newDst
.get(), m_expr1
);
990 generator
.emitJump(afterElse
.get());
992 generator
.emitLabel(beforeElse
.get());
993 generator
.emitNode(newDst
.get(), m_expr2
);
995 generator
.emitLabel(afterElse
.get());
1000 // ------------------------------ ReadModifyResolveNode -----------------------------------
1002 // FIXME: should this be moved to be a method on BytecodeGenerator?
1003 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1014 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1015 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1022 opcodeID
= op_lshift
;
1025 opcodeID
= op_rshift
;
1028 opcodeID
= op_urshift
;
1031 opcodeID
= op_bitand
;
1034 opcodeID
= op_bitxor
;
1037 opcodeID
= op_bitor
;
1043 ASSERT_NOT_REACHED();
1047 RegisterID
* src2
= generator
.emitNode(m_right
);
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());
1054 return generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1057 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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()));
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());
1072 RegisterID
* result
= emitReadModifyAssignment(generator
, local
, local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1073 return generator
.moveToDestinationIfNeeded(dst
, result
);
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
);
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
);
1093 // ------------------------------ AssignResolveNode -----------------------------------
1095 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1097 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1098 if (generator
.isLocalConstant(m_ident
))
1099 return generator
.emitNode(dst
, m_right
);
1101 RegisterID
* result
= generator
.emitNode(local
, m_right
);
1102 return generator
.moveToDestinationIfNeeded(dst
, result
);
1107 JSObject
* globalObject
= 0;
1108 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, globalObject
) && index
!= missingSymbolMarker()) {
1109 if (dst
== generator
.ignoredResult())
1111 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1112 generator
.emitPutScopedVar(depth
, index
, value
, globalObject
);
1116 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1117 if (dst
== generator
.ignoredResult())
1119 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1120 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1121 return generator
.emitPutById(base
.get(), m_ident
, value
);
1124 // ------------------------------ AssignDotNode -----------------------------------
1126 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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
);
1136 // ------------------------------ ReadModifyDotNode -----------------------------------
1138 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1140 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
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()));
1146 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1147 return generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1150 // ------------------------------ AssignErrorNode -----------------------------------
1152 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1154 return emitThrowError(generator
, ReferenceError
, "Left side of assignment is not a reference.");
1157 // ------------------------------ AssignBracketNode -----------------------------------
1159 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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
);
1166 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1167 generator
.emitPutByVal(base
.get(), property
.get(), result
);
1168 return generator
.moveToDestinationIfNeeded(dst
, result
);
1171 // ------------------------------ ReadModifyBracketNode -----------------------------------
1173 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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
));
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()));
1182 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1183 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1185 return updatedValue
;
1188 // ------------------------------ CommaNode ------------------------------------
1190 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
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());
1198 // ------------------------------ ConstDeclNode ------------------------------------
1200 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1202 if (RegisterID
* local
= generator
.constRegisterFor(m_ident
)) {
1206 return generator
.emitNode(local
, m_init
);
1209 // FIXME: While this code should only be hit in eval code, it will potentially
1210 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1211 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1212 RegisterID
* value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1213 return generator
.emitPutById(base
.get(), m_ident
, value
);
1216 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1218 RegisterID
* result
= 0;
1219 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1220 result
= n
->emitCodeSingle(generator
);
1225 // ------------------------------ ConstStatementNode -----------------------------
1227 RegisterID
* ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1229 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1230 return generator
.emitNode(m_next
);
1233 // ------------------------------ Helper functions for handling Vectors of StatementNode -------------------------------
1235 static inline void statementListEmitCode(const StatementVector
& statements
, BytecodeGenerator
& generator
, RegisterID
* dst
)
1237 size_t size
= statements
.size();
1238 for (size_t i
= 0; i
< size
; ++i
)
1239 generator
.emitNode(dst
, statements
[i
]);
1242 // ------------------------------ BlockNode ------------------------------------
1244 RegisterID
* BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1246 statementListEmitCode(m_children
, generator
, dst
);
1250 // ------------------------------ EmptyStatementNode ---------------------------
1252 RegisterID
* EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1254 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1258 // ------------------------------ DebuggerStatementNode ---------------------------
1260 RegisterID
* DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1262 generator
.emitDebugHook(DidReachBreakpoint
, firstLine(), lastLine());
1266 // ------------------------------ ExprStatementNode ----------------------------
1268 RegisterID
* ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1271 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1272 return generator
.emitNode(dst
, m_expr
);
1275 // ------------------------------ VarStatementNode ----------------------------
1277 RegisterID
* VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1280 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1281 return generator
.emitNode(m_expr
);
1284 // ------------------------------ IfNode ---------------------------------------
1286 RegisterID
* IfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1288 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1290 RefPtr
<Label
> afterThen
= generator
.newLabel();
1292 RegisterID
* cond
= generator
.emitNode(m_condition
);
1293 generator
.emitJumpIfFalse(cond
, afterThen
.get());
1295 generator
.emitNode(dst
, m_ifBlock
);
1296 generator
.emitLabel(afterThen
.get());
1298 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1302 // ------------------------------ IfElseNode ---------------------------------------
1304 RegisterID
* IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1306 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1308 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1309 RefPtr
<Label
> afterElse
= generator
.newLabel();
1311 RegisterID
* cond
= generator
.emitNode(m_condition
);
1312 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1314 generator
.emitNode(dst
, m_ifBlock
);
1315 generator
.emitJump(afterElse
.get());
1317 generator
.emitLabel(beforeElse
.get());
1319 generator
.emitNode(dst
, m_elseBlock
);
1321 generator
.emitLabel(afterElse
.get());
1323 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1327 // ------------------------------ DoWhileNode ----------------------------------
1329 RegisterID
* DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1331 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1333 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1334 generator
.emitLabel(topOfLoop
.get());
1336 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1338 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1340 generator
.emitLabel(scope
->continueTarget());
1341 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1342 RegisterID
* cond
= generator
.emitNode(m_expr
);
1343 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1345 generator
.emitLabel(scope
->breakTarget());
1346 return result
.get();
1349 // ------------------------------ WhileNode ------------------------------------
1351 RegisterID
* WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1353 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1355 generator
.emitJump(scope
->continueTarget());
1357 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1358 generator
.emitLabel(topOfLoop
.get());
1360 generator
.emitNode(dst
, m_statement
);
1362 generator
.emitLabel(scope
->continueTarget());
1363 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1364 RegisterID
* cond
= generator
.emitNode(m_expr
);
1365 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1367 generator
.emitLabel(scope
->breakTarget());
1369 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1373 // ------------------------------ ForNode --------------------------------------
1375 RegisterID
* ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1377 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1379 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1382 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
1384 RefPtr
<Label
> condition
= generator
.newLabel();
1385 generator
.emitJump(condition
.get());
1387 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1388 generator
.emitLabel(topOfLoop
.get());
1390 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1392 generator
.emitLabel(scope
->continueTarget());
1393 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1395 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
1397 generator
.emitLabel(condition
.get());
1399 RegisterID
* cond
= generator
.emitNode(m_expr2
);
1400 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1402 generator
.emitJump(topOfLoop
.get());
1404 generator
.emitLabel(scope
->breakTarget());
1405 return result
.get();
1408 // ------------------------------ ForInNode ------------------------------------
1410 RegisterID
* ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1412 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1414 if (!m_lexpr
->isLocation())
1415 return emitThrowError(generator
, ReferenceError
, "Left side of for-in statement is not a reference.");
1417 RefPtr
<Label
> continueTarget
= generator
.newLabel();
1419 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1422 generator
.emitNode(generator
.ignoredResult(), m_init
);
1423 RegisterID
* forInBase
= generator
.emitNode(m_expr
);
1424 RefPtr
<RegisterID
> iter
= generator
.emitGetPropertyNames(generator
.newTemporary(), forInBase
);
1425 generator
.emitJump(scope
->continueTarget());
1427 RefPtr
<Label
> loopStart
= generator
.newLabel();
1428 generator
.emitLabel(loopStart
.get());
1430 RegisterID
* propertyName
;
1431 if (m_lexpr
->isResolveNode()) {
1432 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1433 propertyName
= generator
.registerFor(ident
);
1434 if (!propertyName
) {
1435 propertyName
= generator
.newTemporary();
1436 RefPtr
<RegisterID
> protect
= propertyName
;
1437 RegisterID
* base
= generator
.emitResolveBase(generator
.newTemporary(), ident
);
1439 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1440 generator
.emitPutById(base
, ident
, propertyName
);
1442 } else if (m_lexpr
->isDotAccessorNode()) {
1443 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1444 const Identifier
& ident
= assignNode
->identifier();
1445 propertyName
= generator
.newTemporary();
1446 RefPtr
<RegisterID
> protect
= propertyName
;
1447 RegisterID
* base
= generator
.emitNode(assignNode
->base());
1449 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1450 generator
.emitPutById(base
, ident
, propertyName
);
1452 ASSERT(m_lexpr
->isBracketAccessorNode());
1453 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1454 propertyName
= generator
.newTemporary();
1455 RefPtr
<RegisterID
> protect
= propertyName
;
1456 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1457 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1459 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1460 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
1463 generator
.emitNode(dst
, m_statement
);
1465 generator
.emitLabel(scope
->continueTarget());
1466 generator
.emitNextPropertyName(propertyName
, iter
.get(), loopStart
.get());
1467 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1468 generator
.emitLabel(scope
->breakTarget());
1472 // ------------------------------ ContinueNode ---------------------------------
1475 RegisterID
* ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1477 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1479 LabelScope
* scope
= generator
.continueTarget(m_ident
);
1482 return m_ident
.isEmpty()
1483 ? emitThrowError(generator
, SyntaxError
, "Invalid continue statement.")
1484 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1486 generator
.emitJumpScopes(scope
->continueTarget(), scope
->scopeDepth());
1490 // ------------------------------ BreakNode ------------------------------------
1493 RegisterID
* BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1495 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1497 LabelScope
* scope
= generator
.breakTarget(m_ident
);
1500 return m_ident
.isEmpty()
1501 ? emitThrowError(generator
, SyntaxError
, "Invalid break statement.")
1502 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1504 generator
.emitJumpScopes(scope
->breakTarget(), scope
->scopeDepth());
1508 // ------------------------------ ReturnNode -----------------------------------
1510 RegisterID
* ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1512 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1513 if (generator
.codeType() != FunctionCode
)
1514 return emitThrowError(generator
, SyntaxError
, "Invalid return statement.");
1516 if (dst
== generator
.ignoredResult())
1518 RegisterID
* r0
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
1519 RefPtr
<RegisterID
> returnRegister
;
1520 if (generator
.scopeDepth()) {
1521 RefPtr
<Label
> l0
= generator
.newLabel();
1522 if (generator
.hasFinaliser() && !r0
->isTemporary()) {
1523 returnRegister
= generator
.emitMove(generator
.newTemporary(), r0
);
1524 r0
= returnRegister
.get();
1526 generator
.emitJumpScopes(l0
.get(), 0);
1527 generator
.emitLabel(l0
.get());
1529 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1530 return generator
.emitReturn(r0
);
1533 // ------------------------------ WithNode -------------------------------------
1535 RegisterID
* WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1537 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1539 RefPtr
<RegisterID
> scope
= generator
.newTemporary();
1540 generator
.emitNode(scope
.get(), m_expr
); // scope must be protected until popped
1541 generator
.emitExpressionInfo(m_divot
, m_expressionLength
, 0);
1542 generator
.emitPushScope(scope
.get());
1543 RegisterID
* result
= generator
.emitNode(dst
, m_statement
);
1544 generator
.emitPopScope();
1548 // ------------------------------ CaseBlockNode --------------------------------
1557 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
1559 for (; list
; list
= list
->getNext()) {
1560 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
1561 literalVector
.append(clauseExpression
);
1562 if (clauseExpression
->isNumber()) {
1563 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
1564 int32_t intVal
= static_cast<int32_t>(value
);
1565 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
1566 typeForTable
= SwitchNeither
;
1569 if (intVal
< min_num
)
1571 if (intVal
> max_num
)
1573 typeForTable
= SwitchNumber
;
1576 if (clauseExpression
->isString()) {
1577 if (typeForTable
& ~SwitchString
) {
1578 typeForTable
= SwitchNeither
;
1581 const UString
& value
= static_cast<StringNode
*>(clauseExpression
)->value().ustring();
1582 if (singleCharacterSwitch
&= value
.size() == 1) {
1583 int32_t intVal
= value
.rep()->data()[0];
1584 if (intVal
< min_num
)
1586 if (intVal
> max_num
)
1589 typeForTable
= SwitchString
;
1592 typeForTable
= SwitchNeither
;
1597 SwitchInfo::SwitchType
CaseBlockNode::tryOptimizedSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
1599 SwitchKind typeForTable
= SwitchUnset
;
1600 bool singleCharacterSwitch
= true;
1602 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1603 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1605 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
1606 return SwitchInfo::SwitchNone
;
1608 if (typeForTable
== SwitchNumber
) {
1609 int32_t range
= max_num
- min_num
;
1610 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1611 return SwitchInfo::SwitchImmediate
;
1612 return SwitchInfo::SwitchNone
;
1615 ASSERT(typeForTable
== SwitchString
);
1617 if (singleCharacterSwitch
) {
1618 int32_t range
= max_num
- min_num
;
1619 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1620 return SwitchInfo::SwitchCharacter
;
1623 return SwitchInfo::SwitchString
;
1626 RegisterID
* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
1628 RefPtr
<Label
> defaultLabel
;
1629 Vector
<RefPtr
<Label
>, 8> labelVector
;
1630 Vector
<ExpressionNode
*, 8> literalVector
;
1631 int32_t min_num
= std::numeric_limits
<int32_t>::max();
1632 int32_t max_num
= std::numeric_limits
<int32_t>::min();
1633 SwitchInfo::SwitchType switchType
= tryOptimizedSwitch(literalVector
, min_num
, max_num
);
1635 if (switchType
!= SwitchInfo::SwitchNone
) {
1636 // Prepare the various labels
1637 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
1638 labelVector
.append(generator
.newLabel());
1639 defaultLabel
= generator
.newLabel();
1640 generator
.beginSwitch(switchExpression
, switchType
);
1643 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1644 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1645 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1646 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1647 labelVector
.append(generator
.newLabel());
1648 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1651 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1652 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1653 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1654 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1655 labelVector
.append(generator
.newLabel());
1656 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1658 defaultLabel
= generator
.newLabel();
1659 generator
.emitJump(defaultLabel
.get());
1662 RegisterID
* result
= 0;
1665 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1666 generator
.emitLabel(labelVector
[i
++].get());
1667 statementListEmitCode(list
->getClause()->children(), generator
, dst
);
1670 if (m_defaultClause
) {
1671 generator
.emitLabel(defaultLabel
.get());
1672 statementListEmitCode(m_defaultClause
->children(), generator
, dst
);
1675 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1676 generator
.emitLabel(labelVector
[i
++].get());
1677 statementListEmitCode(list
->getClause()->children(), generator
, dst
);
1679 if (!m_defaultClause
)
1680 generator
.emitLabel(defaultLabel
.get());
1682 ASSERT(i
== labelVector
.size());
1683 if (switchType
!= SwitchInfo::SwitchNone
) {
1684 ASSERT(labelVector
.size() == literalVector
.size());
1685 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
1690 // ------------------------------ SwitchNode -----------------------------------
1692 RegisterID
* SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1694 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1696 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Switch
);
1698 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
1699 RegisterID
* r1
= m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
1701 generator
.emitLabel(scope
->breakTarget());
1705 // ------------------------------ LabelNode ------------------------------------
1707 RegisterID
* LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1709 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1711 if (generator
.breakTarget(m_name
))
1712 return emitThrowError(generator
, SyntaxError
, "Duplicate label: %s.", m_name
);
1714 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
1715 RegisterID
* r0
= generator
.emitNode(dst
, m_statement
);
1717 generator
.emitLabel(scope
->breakTarget());
1721 // ------------------------------ ThrowNode ------------------------------------
1723 RegisterID
* ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1725 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1727 if (dst
== generator
.ignoredResult())
1729 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
1730 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1731 generator
.emitThrow(expr
.get());
1735 // ------------------------------ TryNode --------------------------------------
1737 RegisterID
* TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1739 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1740 // optimizer knows they may be jumped to from anywhere.
1742 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1744 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
1745 RefPtr
<Label
> finallyStart
;
1746 RefPtr
<RegisterID
> finallyReturnAddr
;
1747 if (m_finallyBlock
) {
1748 finallyStart
= generator
.newLabel();
1749 finallyReturnAddr
= generator
.newTemporary();
1750 generator
.pushFinallyContext(finallyStart
.get(), finallyReturnAddr
.get());
1753 generator
.emitLabel(tryStartLabel
.get());
1754 generator
.emitNode(dst
, m_tryBlock
);
1757 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
1759 // Normal path: jump over the catch block.
1760 generator
.emitJump(catchEndLabel
.get());
1762 // Uncaught exception path: the catch block.
1763 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1764 RefPtr
<RegisterID
> exceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1765 if (m_catchHasEval
) {
1766 RefPtr
<RegisterID
> dynamicScopeObject
= generator
.emitNewObject(generator
.newTemporary());
1767 generator
.emitPutById(dynamicScopeObject
.get(), m_exceptionIdent
, exceptionRegister
.get());
1768 generator
.emitMove(exceptionRegister
.get(), dynamicScopeObject
.get());
1769 generator
.emitPushScope(exceptionRegister
.get());
1771 generator
.emitPushNewScope(exceptionRegister
.get(), m_exceptionIdent
, exceptionRegister
.get());
1772 generator
.emitNode(dst
, m_catchBlock
);
1773 generator
.emitPopScope();
1774 generator
.emitLabel(catchEndLabel
.get());
1777 if (m_finallyBlock
) {
1778 generator
.popFinallyContext();
1779 // there may be important registers live at the time we jump
1780 // to a finally block (such as for a return or throw) so we
1781 // ref the highest register ever used as a conservative
1782 // approach to not clobbering anything important
1783 RefPtr
<RegisterID
> highestUsedRegister
= generator
.highestUsedRegister();
1784 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
1786 // Normal path: invoke the finally block, then jump over it.
1787 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1788 generator
.emitJump(finallyEndLabel
.get());
1790 // Uncaught exception path: invoke the finally block, then re-throw the exception.
1791 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1792 RefPtr
<RegisterID
> tempExceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1793 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1794 generator
.emitThrow(tempExceptionRegister
.get());
1796 // The finally block.
1797 generator
.emitLabel(finallyStart
.get());
1798 generator
.emitNode(dst
, m_finallyBlock
);
1799 generator
.emitSubroutineReturn(finallyReturnAddr
.get());
1801 generator
.emitLabel(finallyEndLabel
.get());
1807 // -----------------------------ScopeNodeData ---------------------------
1809 ScopeNodeData::ScopeNodeData(ParserArena
& arena
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, int numConstants
)
1810 : m_numConstants(numConstants
)
1812 m_arena
.swap(arena
);
1814 m_varStack
.swap(*varStack
);
1816 m_functionStack
.swap(*funcStack
);
1818 children
->releaseContentsIntoVector(m_children
);
1821 void ScopeNodeData::mark()
1823 FunctionStack::iterator end
= m_functionStack
.end();
1824 for (FunctionStack::iterator ptr
= m_functionStack
.begin(); ptr
!= end
; ++ptr
) {
1825 FunctionBodyNode
* body
= (*ptr
)->body();
1826 if (!body
->isGenerated())
1828 body
->generatedBytecode().mark();
1832 // ------------------------------ ScopeNode -----------------------------
1834 ScopeNode::ScopeNode(JSGlobalData
* globalData
)
1835 : StatementNode(globalData
)
1836 , ParserArenaRefCounted(globalData
)
1837 , m_features(NoFeatures
)
1839 #if ENABLE(CODEBLOCK_SAMPLING)
1840 if (SamplingTool
* sampler
= globalData
->interpreter
->sampler())
1841 sampler
->notifyOfScope(this);
1845 ScopeNode::ScopeNode(JSGlobalData
* globalData
, const SourceCode
& source
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, CodeFeatures features
, int numConstants
)
1846 : StatementNode(globalData
)
1847 , ParserArenaRefCounted(globalData
)
1848 , m_data(new ScopeNodeData(globalData
->parser
->arena(), children
, varStack
, funcStack
, numConstants
))
1849 , m_features(features
)
1852 #if ENABLE(CODEBLOCK_SAMPLING)
1853 if (SamplingTool
* sampler
= globalData
->interpreter
->sampler())
1854 sampler
->notifyOfScope(this);
1858 // ------------------------------ ProgramNode -----------------------------
1860 inline ProgramNode::ProgramNode(JSGlobalData
* globalData
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, const SourceCode
& source
, CodeFeatures features
, int numConstants
)
1861 : ScopeNode(globalData
, source
, children
, varStack
, funcStack
, features
, numConstants
)
1865 PassRefPtr
<ProgramNode
> ProgramNode::create(JSGlobalData
* globalData
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, const SourceCode
& source
, CodeFeatures features
, int numConstants
)
1867 RefPtr
<ProgramNode
> node
= new ProgramNode(globalData
, children
, varStack
, funcStack
, source
, features
, numConstants
);
1869 ASSERT(node
->data()->m_arena
.last() == node
);
1870 node
->data()->m_arena
.removeLast();
1871 ASSERT(!node
->data()->m_arena
.contains(node
.get()));
1873 return node
.release();
1876 RegisterID
* ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1878 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1880 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1881 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1882 statementListEmitCode(children(), generator
, dstRegister
.get());
1884 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1885 generator
.emitEnd(dstRegister
.get());
1889 void ProgramNode::generateBytecode(ScopeChainNode
* scopeChainNode
)
1891 ScopeChain
scopeChain(scopeChainNode
);
1892 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
1894 m_code
.set(new ProgramCodeBlock(this, GlobalCode
, globalObject
, source().provider()));
1896 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(this, globalObject
->debugger(), scopeChain
, &globalObject
->symbolTable(), m_code
.get()));
1897 generator
->generate();
1903 void ProgramNode::generateJITCode(ScopeChainNode
* scopeChainNode
)
1905 bytecode(scopeChainNode
);
1908 JIT::compile(scopeChainNode
->globalData
, m_code
.get());
1913 // ------------------------------ EvalNode -----------------------------
1915 inline EvalNode::EvalNode(JSGlobalData
* globalData
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, const SourceCode
& source
, CodeFeatures features
, int numConstants
)
1916 : ScopeNode(globalData
, source
, children
, varStack
, funcStack
, features
, numConstants
)
1920 PassRefPtr
<EvalNode
> EvalNode::create(JSGlobalData
* globalData
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, const SourceCode
& source
, CodeFeatures features
, int numConstants
)
1922 RefPtr
<EvalNode
> node
= new EvalNode(globalData
, children
, varStack
, funcStack
, source
, features
, numConstants
);
1924 ASSERT(node
->data()->m_arena
.last() == node
);
1925 node
->data()->m_arena
.removeLast();
1926 ASSERT(!node
->data()->m_arena
.contains(node
.get()));
1928 return node
.release();
1931 RegisterID
* EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1933 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1935 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1936 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1937 statementListEmitCode(children(), generator
, dstRegister
.get());
1939 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1940 generator
.emitEnd(dstRegister
.get());
1944 void EvalNode::generateBytecode(ScopeChainNode
* scopeChainNode
)
1946 ScopeChain
scopeChain(scopeChainNode
);
1947 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
1949 m_code
.set(new EvalCodeBlock(this, globalObject
, source().provider(), scopeChain
.localDepth()));
1951 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(this, globalObject
->debugger(), scopeChain
, &m_code
->symbolTable(), m_code
.get()));
1952 generator
->generate();
1954 // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time,
1955 // so the entire ScopeNodeData cannot be destoyed.
1959 EvalCodeBlock
& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode
* scopeChainNode
, CodeBlock
* codeBlockBeingRegeneratedFrom
)
1963 ScopeChain
scopeChain(scopeChainNode
);
1964 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
1966 m_code
.set(new EvalCodeBlock(this, globalObject
, source().provider(), scopeChain
.localDepth()));
1968 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(this, globalObject
->debugger(), scopeChain
, &m_code
->symbolTable(), m_code
.get()));
1969 generator
->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom
);
1970 generator
->generate();
1975 void EvalNode::mark()
1977 // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that
1982 void EvalNode::generateJITCode(ScopeChainNode
* scopeChainNode
)
1984 bytecode(scopeChainNode
);
1987 JIT::compile(scopeChainNode
->globalData
, m_code
.get());
1992 // ------------------------------ FunctionBodyNode -----------------------------
1994 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData
* globalData
)
1995 : ScopeNode(globalData
)
1997 , m_parameterCount(0)
2001 inline FunctionBodyNode::FunctionBodyNode(JSGlobalData
* globalData
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, const SourceCode
& sourceCode
, CodeFeatures features
, int numConstants
)
2002 : ScopeNode(globalData
, sourceCode
, children
, varStack
, funcStack
, features
, numConstants
)
2004 , m_parameterCount(0)
2008 FunctionBodyNode::~FunctionBodyNode()
2010 for (size_t i
= 0; i
< m_parameterCount
; ++i
)
2011 m_parameters
[i
].~Identifier();
2012 fastFree(m_parameters
);
2015 void FunctionBodyNode::finishParsing(const SourceCode
& source
, ParameterNode
* firstParameter
)
2017 Vector
<Identifier
> parameters
;
2018 for (ParameterNode
* parameter
= firstParameter
; parameter
; parameter
= parameter
->nextParam())
2019 parameters
.append(parameter
->ident());
2020 size_t count
= parameters
.size();
2023 finishParsing(parameters
.releaseBuffer(), count
);
2026 void FunctionBodyNode::finishParsing(Identifier
* parameters
, size_t parameterCount
)
2028 ASSERT(!source().isNull());
2029 m_parameters
= parameters
;
2030 m_parameterCount
= parameterCount
;
2033 void FunctionBodyNode::mark()
2040 PassRefPtr
<FunctionBodyNode
> FunctionBodyNode::createNativeThunk(JSGlobalData
* globalData
)
2042 RefPtr
<FunctionBodyNode
> body
= new FunctionBodyNode(globalData
);
2043 globalData
->parser
->arena().reset();
2044 body
->m_code
.set(new CodeBlock(body
.get()));
2045 body
->m_jitCode
= JITCode(JITCode::HostFunction(globalData
->jitStubs
.ctiNativeCallThunk()));
2046 return body
.release();
2050 bool FunctionBodyNode::isHostFunction() const
2052 return m_code
&& m_code
->codeType() == NativeCode
;
2055 FunctionBodyNode
* FunctionBodyNode::create(JSGlobalData
* globalData
)
2057 return new FunctionBodyNode(globalData
);
2060 PassRefPtr
<FunctionBodyNode
> FunctionBodyNode::create(JSGlobalData
* globalData
, SourceElements
* children
, VarStack
* varStack
, FunctionStack
* funcStack
, const SourceCode
& sourceCode
, CodeFeatures features
, int numConstants
)
2062 RefPtr
<FunctionBodyNode
> node
= new FunctionBodyNode(globalData
, children
, varStack
, funcStack
, sourceCode
, features
, numConstants
);
2064 ASSERT(node
->data()->m_arena
.last() == node
);
2065 node
->data()->m_arena
.removeLast();
2066 ASSERT(!node
->data()->m_arena
.contains(node
.get()));
2068 return node
.release();
2071 void FunctionBodyNode::generateBytecode(ScopeChainNode
* scopeChainNode
)
2073 // This branch is only necessary since you can still create a non-stub FunctionBodyNode by
2074 // calling Parser::parse<FunctionBodyNode>().
2076 scopeChainNode
->globalData
->parser
->reparseInPlace(scopeChainNode
->globalData
, this);
2079 ScopeChain
scopeChain(scopeChainNode
);
2080 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
2082 m_code
.set(new CodeBlock(this, FunctionCode
, source().provider(), source().startOffset()));
2084 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(this, globalObject
->debugger(), scopeChain
, &m_code
->symbolTable(), m_code
.get()));
2085 generator
->generate();
2091 void FunctionBodyNode::generateJITCode(ScopeChainNode
* scopeChainNode
)
2093 bytecode(scopeChainNode
);
2096 JIT::compile(scopeChainNode
->globalData
, m_code
.get());
2101 CodeBlock
& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode
* scopeChainNode
, CodeBlock
* codeBlockBeingRegeneratedFrom
)
2105 ScopeChain
scopeChain(scopeChainNode
);
2106 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
2108 m_code
.set(new CodeBlock(this, FunctionCode
, source().provider(), source().startOffset()));
2110 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(this, globalObject
->debugger(), scopeChain
, &m_code
->symbolTable(), m_code
.get()));
2111 generator
->setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom
);
2112 generator
->generate();
2117 RegisterID
* FunctionBodyNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2119 generator
.emitDebugHook(DidEnterCallFrame
, firstLine(), lastLine());
2120 statementListEmitCode(children(), generator
, generator
.ignoredResult());
2121 if (children().size() && children().last()->isBlock()) {
2122 BlockNode
* blockNode
= static_cast<BlockNode
*>(children().last());
2123 if (blockNode
->children().size() && blockNode
->children().last()->isReturnNode())
2127 RegisterID
* r0
= generator
.emitLoad(0, jsUndefined());
2128 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
2129 generator
.emitReturn(r0
);
2133 UString
FunctionBodyNode::paramString() const
2136 for (size_t pos
= 0; pos
< m_parameterCount
; ++pos
) {
2139 s
+= parameters()[pos
].ustring();
2145 Identifier
* FunctionBodyNode::copyParameters()
2147 Identifier
* parameters
= static_cast<Identifier
*>(fastMalloc(m_parameterCount
* sizeof(Identifier
)));
2148 VectorCopier
<false, Identifier
>::uninitializedCopy(m_parameters
, m_parameters
+ m_parameterCount
, parameters
);
2152 // ------------------------------ FuncDeclNode ---------------------------------
2154 JSFunction
* FuncDeclNode::makeFunction(ExecState
* exec
, ScopeChainNode
* scopeChain
)
2156 return new (exec
) JSFunction(exec
, m_ident
, m_body
.get(), scopeChain
);
2159 RegisterID
* FuncDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2161 if (dst
== generator
.ignoredResult())
2166 // ------------------------------ FuncExprNode ---------------------------------
2168 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2170 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);
2173 JSFunction
* FuncExprNode::makeFunction(ExecState
* exec
, ScopeChainNode
* scopeChain
)
2175 JSFunction
* func
= new (exec
) JSFunction(exec
, m_ident
, m_body
.get(), scopeChain
);
2178 The Identifier in a FunctionExpression can be referenced from inside
2179 the FunctionExpression's FunctionBody to allow the function to call
2180 itself recursively. However, unlike in a FunctionDeclaration, the
2181 Identifier in a FunctionExpression cannot be referenced from and
2182 does not affect the scope enclosing the FunctionExpression.
2185 if (!m_ident
.isNull()) {
2186 JSStaticScopeObject
* functionScopeObject
= new (exec
) JSStaticScopeObject(exec
, m_ident
, func
, ReadOnly
| DontDelete
);
2187 func
->scope().push(functionScopeObject
);