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>
53 Details of the emitBytecode function.
55 Return value: The register holding the production's value.
56 dst: An optional parameter specifying the most efficient destination at
57 which to store the production's value. The callee must honor dst.
59 The dst argument provides for a crude form of copy propagation. For example,
72 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
75 // ------------------------------ ThrowableExpressionData --------------------------------
77 static void substitute(UString
& string
, const UString
& substring
)
79 int position
= string
.find("%s");
80 ASSERT(position
!= -1);
81 string
= makeString(string
.substr(0, position
), substring
, string
.substr(position
+ 2));
84 RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType type
, const char* message
)
86 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
87 RegisterID
* exception
= generator
.emitNewError(generator
.newTemporary(), type
, jsString(generator
.globalData(), message
));
88 generator
.emitThrow(exception
);
92 RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType type
, const char* messageTemplate
, const UString
& label
)
94 UString message
= messageTemplate
;
95 substitute(message
, label
);
96 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
97 RegisterID
* exception
= generator
.emitNewError(generator
.newTemporary(), type
, jsString(generator
.globalData(), message
));
98 generator
.emitThrow(exception
);
102 inline RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType type
, const char* messageTemplate
, const Identifier
& label
)
104 return emitThrowError(generator
, type
, messageTemplate
, label
.ustring());
107 // ------------------------------ NullNode -------------------------------------
109 RegisterID
* NullNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
111 if (dst
== generator
.ignoredResult())
113 return generator
.emitLoad(dst
, jsNull());
116 // ------------------------------ BooleanNode ----------------------------------
118 RegisterID
* BooleanNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
120 if (dst
== generator
.ignoredResult())
122 return generator
.emitLoad(dst
, m_value
);
125 // ------------------------------ NumberNode -----------------------------------
127 RegisterID
* NumberNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
129 if (dst
== generator
.ignoredResult())
131 return generator
.emitLoad(dst
, m_value
);
134 // ------------------------------ StringNode -----------------------------------
136 RegisterID
* StringNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
138 if (dst
== generator
.ignoredResult())
140 return generator
.emitLoad(dst
, m_value
);
143 // ------------------------------ RegExpNode -----------------------------------
145 RegisterID
* RegExpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
147 RefPtr
<RegExp
> regExp
= RegExp::create(generator
.globalData(), m_pattern
.ustring(), m_flags
.ustring());
148 if (!regExp
->isValid())
149 return emitThrowError(generator
, SyntaxError
, "Invalid regular expression: %s", regExp
->errorMessage());
150 if (dst
== generator
.ignoredResult())
152 return generator
.emitNewRegExp(generator
.finalDestination(dst
), regExp
.get());
155 // ------------------------------ ThisNode -------------------------------------
157 RegisterID
* ThisNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
159 if (dst
== generator
.ignoredResult())
161 return generator
.moveToDestinationIfNeeded(dst
, generator
.thisRegister());
164 // ------------------------------ ResolveNode ----------------------------------
166 bool ResolveNode::isPure(BytecodeGenerator
& generator
) const
168 return generator
.isLocal(m_ident
);
171 RegisterID
* ResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
173 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
174 if (dst
== generator
.ignoredResult())
176 return generator
.moveToDestinationIfNeeded(dst
, local
);
179 generator
.emitExpressionInfo(m_startOffset
+ m_ident
.size(), m_ident
.size(), 0);
180 return generator
.emitResolve(generator
.finalDestination(dst
), m_ident
);
183 // ------------------------------ ArrayNode ------------------------------------
185 RegisterID
* ArrayNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
187 // FIXME: Should we put all of this code into emitNewArray?
190 ElementNode
* firstPutElement
;
191 for (firstPutElement
= m_element
; firstPutElement
; firstPutElement
= firstPutElement
->next()) {
192 if (firstPutElement
->elision())
197 if (!firstPutElement
&& !m_elision
)
198 return generator
.emitNewArray(generator
.finalDestination(dst
), m_element
);
200 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.tempDestination(dst
), m_element
);
202 for (ElementNode
* n
= firstPutElement
; n
; n
= n
->next()) {
203 RegisterID
* value
= generator
.emitNode(n
->value());
204 length
+= n
->elision();
205 generator
.emitPutByIndex(array
.get(), length
++, value
);
209 RegisterID
* value
= generator
.emitLoad(0, jsNumber(generator
.globalData(), m_elision
+ length
));
210 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, value
);
213 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
216 bool ArrayNode::isSimpleArray() const
218 if (m_elision
|| m_optional
)
220 for (ElementNode
* ptr
= m_element
; ptr
; ptr
= ptr
->next()) {
227 ArgumentListNode
* ArrayNode::toArgumentList(JSGlobalData
* globalData
) const
229 ASSERT(!m_elision
&& !m_optional
);
230 ElementNode
* ptr
= m_element
;
233 ArgumentListNode
* head
= new (globalData
) ArgumentListNode(globalData
, ptr
->value());
234 ArgumentListNode
* tail
= head
;
236 for (; ptr
; ptr
= ptr
->next()) {
237 ASSERT(!ptr
->elision());
238 tail
= new (globalData
) ArgumentListNode(globalData
, tail
, ptr
->value());
243 // ------------------------------ ObjectLiteralNode ----------------------------
245 RegisterID
* ObjectLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
248 if (dst
== generator
.ignoredResult())
250 return generator
.emitNewObject(generator
.finalDestination(dst
));
252 return generator
.emitNode(dst
, m_list
);
255 // ------------------------------ PropertyListNode -----------------------------
257 RegisterID
* PropertyListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
259 RefPtr
<RegisterID
> newObj
= generator
.tempDestination(dst
);
261 generator
.emitNewObject(newObj
.get());
263 for (PropertyListNode
* p
= this; p
; p
= p
->m_next
) {
264 RegisterID
* value
= generator
.emitNode(p
->m_node
->m_assign
);
266 switch (p
->m_node
->m_type
) {
267 case PropertyNode::Constant
: {
268 generator
.emitPutById(newObj
.get(), p
->m_node
->name(), value
);
271 case PropertyNode::Getter
: {
272 generator
.emitPutGetter(newObj
.get(), p
->m_node
->name(), value
);
275 case PropertyNode::Setter
: {
276 generator
.emitPutSetter(newObj
.get(), p
->m_node
->name(), value
);
280 ASSERT_NOT_REACHED();
284 return generator
.moveToDestinationIfNeeded(dst
, newObj
.get());
287 // ------------------------------ BracketAccessorNode --------------------------------
289 RegisterID
* BracketAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
291 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
, m_subscript
->isPure(generator
));
292 RegisterID
* property
= generator
.emitNode(m_subscript
);
293 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
294 return generator
.emitGetByVal(generator
.finalDestination(dst
), base
.get(), property
);
297 // ------------------------------ DotAccessorNode --------------------------------
299 RegisterID
* DotAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
301 RegisterID
* base
= generator
.emitNode(m_base
);
302 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
303 return generator
.emitGetById(generator
.finalDestination(dst
), base
, m_ident
);
306 // ------------------------------ ArgumentListNode -----------------------------
308 RegisterID
* ArgumentListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
311 return generator
.emitNode(dst
, m_expr
);
314 // ------------------------------ NewExprNode ----------------------------------
316 RegisterID
* NewExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
318 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
319 return generator
.emitConstruct(generator
.finalDestination(dst
), func
.get(), m_args
, divot(), startOffset(), endOffset());
322 // ------------------------------ EvalFunctionCallNode ----------------------------------
324 RegisterID
* EvalFunctionCallNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
326 RefPtr
<RegisterID
> func
= generator
.tempDestination(dst
);
327 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
328 generator
.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
329 generator
.emitResolveWithBase(thisRegister
.get(), func
.get(), generator
.propertyNames().eval
);
330 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
333 // ------------------------------ FunctionCallValueNode ----------------------------------
335 RegisterID
* FunctionCallValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
337 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
338 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsNull());
339 return generator
.emitCall(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
342 // ------------------------------ FunctionCallResolveNode ----------------------------------
344 RegisterID
* FunctionCallResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
346 if (RefPtr
<RegisterID
> local
= generator
.registerFor(m_ident
)) {
347 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsNull());
348 return generator
.emitCall(generator
.finalDestination(dst
, thisRegister
.get()), local
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
353 JSObject
* globalObject
= 0;
354 if (generator
.findScopedProperty(m_ident
, index
, depth
, false, globalObject
) && index
!= missingSymbolMarker()) {
355 RefPtr
<RegisterID
> func
= generator
.emitGetScopedVar(generator
.newTemporary(), depth
, index
, globalObject
);
356 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsNull());
357 return generator
.emitCall(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
360 RefPtr
<RegisterID
> func
= generator
.newTemporary();
361 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
362 int identifierStart
= divot() - startOffset();
363 generator
.emitExpressionInfo(identifierStart
+ m_ident
.size(), m_ident
.size(), 0);
364 generator
.emitResolveWithBase(thisRegister
.get(), func
.get(), m_ident
);
365 return generator
.emitCall(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
368 // ------------------------------ FunctionCallBracketNode ----------------------------------
370 RegisterID
* FunctionCallBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
372 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
373 RegisterID
* property
= generator
.emitNode(m_subscript
);
374 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
375 RefPtr
<RegisterID
> function
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
);
376 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
377 return generator
.emitCall(generator
.finalDestination(dst
, function
.get()), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
380 // ------------------------------ FunctionCallDotNode ----------------------------------
382 RegisterID
* FunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
384 RefPtr
<RegisterID
> function
= generator
.tempDestination(dst
);
385 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
386 generator
.emitNode(thisRegister
.get(), m_base
);
387 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
388 generator
.emitMethodCheck();
389 generator
.emitGetById(function
.get(), thisRegister
.get(), m_ident
);
390 return generator
.emitCall(generator
.finalDestination(dst
, function
.get()), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
393 RegisterID
* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
395 RefPtr
<Label
> realCall
= generator
.newLabel();
396 RefPtr
<Label
> end
= generator
.newLabel();
397 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
398 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
399 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
400 RefPtr
<RegisterID
> finalDestination
= generator
.finalDestination(dst
, function
.get());
401 generator
.emitJumpIfNotFunctionCall(function
.get(), realCall
.get());
403 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
404 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
405 ArgumentListNode
* oldList
= m_args
->m_listNode
;
406 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
407 generator
.emitNode(thisRegister
.get(), m_args
->m_listNode
->m_expr
);
408 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
410 generator
.emitLoad(thisRegister
.get(), jsNull());
412 generator
.emitCall(finalDestination
.get(), realFunction
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
413 generator
.emitJump(end
.get());
414 m_args
->m_listNode
= oldList
;
416 generator
.emitLabel(realCall
.get());
418 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
419 generator
.emitCall(finalDestination
.get(), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
421 generator
.emitLabel(end
.get());
422 return finalDestination
.get();
425 static bool areTrivialApplyArguments(ArgumentsNode
* args
)
427 return !args
->m_listNode
|| !args
->m_listNode
->m_expr
|| !args
->m_listNode
->m_next
428 || (!args
->m_listNode
->m_next
->m_next
&& args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
431 RegisterID
* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
433 // A few simple cases can be trivially handled as ordinary function calls.
434 // function.apply(), function.apply(arg) -> identical to function.call
435 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
436 bool mayBeCall
= areTrivialApplyArguments(m_args
);
438 RefPtr
<Label
> realCall
= generator
.newLabel();
439 RefPtr
<Label
> end
= generator
.newLabel();
440 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
441 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
442 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
443 RefPtr
<RegisterID
> finalDestination
= generator
.finalDestination(dst
, function
.get());
444 generator
.emitJumpIfNotFunctionApply(function
.get(), realCall
.get());
447 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
448 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
449 ArgumentListNode
* oldList
= m_args
->m_listNode
;
450 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
451 generator
.emitNode(thisRegister
.get(), m_args
->m_listNode
->m_expr
);
452 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
453 if (m_args
->m_listNode
) {
454 ASSERT(m_args
->m_listNode
->m_expr
->isSimpleArray());
455 ASSERT(!m_args
->m_listNode
->m_next
);
456 m_args
->m_listNode
= static_cast<ArrayNode
*>(m_args
->m_listNode
->m_expr
)->toArgumentList(generator
.globalData());
459 generator
.emitLoad(thisRegister
.get(), jsNull());
460 generator
.emitCall(finalDestination
.get(), realFunction
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
461 m_args
->m_listNode
= oldList
;
463 ASSERT(m_args
->m_listNode
&& m_args
->m_listNode
->m_next
);
464 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.newTemporary(), base
.get());
465 RefPtr
<RegisterID
> argsCountRegister
= generator
.newTemporary();
466 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
467 RefPtr
<RegisterID
> argsRegister
= generator
.newTemporary();
468 generator
.emitNode(thisRegister
.get(), m_args
->m_listNode
->m_expr
);
469 ArgumentListNode
* args
= m_args
->m_listNode
->m_next
;
470 bool isArgumentsApply
= false;
471 if (args
->m_expr
->isResolveNode()) {
472 ResolveNode
* resolveNode
= static_cast<ResolveNode
*>(args
->m_expr
);
473 isArgumentsApply
= generator
.willResolveToArguments(resolveNode
->identifier());
474 if (isArgumentsApply
)
475 generator
.emitMove(argsRegister
.get(), generator
.uncheckedRegisterForArguments());
477 if (!isArgumentsApply
)
478 generator
.emitNode(argsRegister
.get(), args
->m_expr
);
479 while ((args
= args
->m_next
))
480 generator
.emitNode(args
->m_expr
);
482 generator
.emitLoadVarargs(argsCountRegister
.get(), argsRegister
.get());
483 generator
.emitCallVarargs(finalDestination
.get(), realFunction
.get(), thisRegister
.get(), argsCountRegister
.get(), divot(), startOffset(), endOffset());
485 generator
.emitJump(end
.get());
487 generator
.emitLabel(realCall
.get());
489 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
490 generator
.emitCall(finalDestination
.get(), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
492 generator
.emitLabel(end
.get());
493 return finalDestination
.get();
496 // ------------------------------ PostfixResolveNode ----------------------------------
498 static RegisterID
* emitPreIncOrDec(BytecodeGenerator
& generator
, RegisterID
* srcDst
, Operator oper
)
500 return (oper
== OpPlusPlus
) ? generator
.emitPreInc(srcDst
) : generator
.emitPreDec(srcDst
);
503 static RegisterID
* emitPostIncOrDec(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* srcDst
, Operator oper
)
506 return generator
.emitToJSNumber(dst
, srcDst
);
507 return (oper
== OpPlusPlus
) ? generator
.emitPostInc(dst
, srcDst
) : generator
.emitPostDec(dst
, srcDst
);
510 RegisterID
* PostfixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
512 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
513 if (generator
.isLocalConstant(m_ident
)) {
514 if (dst
== generator
.ignoredResult())
516 return generator
.emitToJSNumber(generator
.finalDestination(dst
), local
);
519 if (dst
== generator
.ignoredResult())
520 return emitPreIncOrDec(generator
, local
, m_operator
);
521 return emitPostIncOrDec(generator
, generator
.finalDestination(dst
), local
, m_operator
);
526 JSObject
* globalObject
= 0;
527 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, globalObject
) && index
!= missingSymbolMarker()) {
528 RefPtr
<RegisterID
> value
= generator
.emitGetScopedVar(generator
.newTemporary(), depth
, index
, globalObject
);
529 RegisterID
* oldValue
;
530 if (dst
== generator
.ignoredResult()) {
532 emitPreIncOrDec(generator
, value
.get(), m_operator
);
534 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
536 generator
.emitPutScopedVar(depth
, index
, value
.get(), globalObject
);
540 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
541 RefPtr
<RegisterID
> value
= generator
.newTemporary();
542 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), value
.get(), m_ident
);
543 RegisterID
* oldValue
;
544 if (dst
== generator
.ignoredResult()) {
546 emitPreIncOrDec(generator
, value
.get(), m_operator
);
548 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
550 generator
.emitPutById(base
.get(), m_ident
, value
.get());
554 // ------------------------------ PostfixBracketNode ----------------------------------
556 RegisterID
* PostfixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
558 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
559 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
561 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
562 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.newTemporary(), base
.get(), property
.get());
563 RegisterID
* oldValue
;
564 if (dst
== generator
.ignoredResult()) {
566 if (m_operator
== OpPlusPlus
)
567 generator
.emitPreInc(value
.get());
569 generator
.emitPreDec(value
.get());
571 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
573 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
574 generator
.emitPutByVal(base
.get(), property
.get(), value
.get());
578 // ------------------------------ PostfixDotNode ----------------------------------
580 RegisterID
* PostfixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
582 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
584 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
585 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.newTemporary(), base
.get(), m_ident
);
586 RegisterID
* oldValue
;
587 if (dst
== generator
.ignoredResult()) {
589 if (m_operator
== OpPlusPlus
)
590 generator
.emitPreInc(value
.get());
592 generator
.emitPreDec(value
.get());
594 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
596 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
597 generator
.emitPutById(base
.get(), m_ident
, value
.get());
601 // ------------------------------ PostfixErrorNode -----------------------------------
603 RegisterID
* PostfixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
605 return emitThrowError(generator
, ReferenceError
, m_operator
== OpPlusPlus
606 ? "Postfix ++ operator applied to value that is not a reference."
607 : "Postfix -- operator applied to value that is not a reference.");
610 // ------------------------------ DeleteResolveNode -----------------------------------
612 RegisterID
* DeleteResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
614 if (generator
.registerFor(m_ident
))
615 return generator
.emitLoad(generator
.finalDestination(dst
), false);
617 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
618 RegisterID
* base
= generator
.emitResolveBase(generator
.tempDestination(dst
), m_ident
);
619 return generator
.emitDeleteById(generator
.finalDestination(dst
, base
), base
, m_ident
);
622 // ------------------------------ DeleteBracketNode -----------------------------------
624 RegisterID
* DeleteBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
626 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
627 RegisterID
* r1
= generator
.emitNode(m_subscript
);
629 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
630 return generator
.emitDeleteByVal(generator
.finalDestination(dst
), r0
.get(), r1
);
633 // ------------------------------ DeleteDotNode -----------------------------------
635 RegisterID
* DeleteDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
637 RegisterID
* r0
= generator
.emitNode(m_base
);
639 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
640 return generator
.emitDeleteById(generator
.finalDestination(dst
), r0
, m_ident
);
643 // ------------------------------ DeleteValueNode -----------------------------------
645 RegisterID
* DeleteValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
647 generator
.emitNode(generator
.ignoredResult(), m_expr
);
649 // delete on a non-location expression ignores the value and returns true
650 return generator
.emitLoad(generator
.finalDestination(dst
), true);
653 // ------------------------------ VoidNode -------------------------------------
655 RegisterID
* VoidNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
657 if (dst
== generator
.ignoredResult()) {
658 generator
.emitNode(generator
.ignoredResult(), m_expr
);
661 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
662 return generator
.emitLoad(dst
, jsUndefined());
665 // ------------------------------ TypeOfValueNode -----------------------------------
667 RegisterID
* TypeOfResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
669 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
670 if (dst
== generator
.ignoredResult())
672 return generator
.emitTypeOf(generator
.finalDestination(dst
), local
);
675 RefPtr
<RegisterID
> scratch
= generator
.emitResolveBase(generator
.tempDestination(dst
), m_ident
);
676 generator
.emitGetById(scratch
.get(), scratch
.get(), m_ident
);
677 if (dst
== generator
.ignoredResult())
679 return generator
.emitTypeOf(generator
.finalDestination(dst
, scratch
.get()), scratch
.get());
682 // ------------------------------ TypeOfValueNode -----------------------------------
684 RegisterID
* TypeOfValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
686 if (dst
== generator
.ignoredResult()) {
687 generator
.emitNode(generator
.ignoredResult(), m_expr
);
690 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
691 return generator
.emitTypeOf(generator
.finalDestination(dst
), src
.get());
694 // ------------------------------ PrefixResolveNode ----------------------------------
696 RegisterID
* PrefixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
698 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
699 if (generator
.isLocalConstant(m_ident
)) {
700 if (dst
== generator
.ignoredResult())
702 RefPtr
<RegisterID
> r0
= generator
.emitLoad(generator
.finalDestination(dst
), (m_operator
== OpPlusPlus
) ? 1.0 : -1.0);
703 return generator
.emitBinaryOp(op_add
, r0
.get(), local
, r0
.get(), OperandTypes());
706 emitPreIncOrDec(generator
, local
, m_operator
);
707 return generator
.moveToDestinationIfNeeded(dst
, local
);
712 JSObject
* globalObject
= 0;
713 if (generator
.findScopedProperty(m_ident
, index
, depth
, false, globalObject
) && index
!= missingSymbolMarker()) {
714 RefPtr
<RegisterID
> propDst
= generator
.emitGetScopedVar(generator
.tempDestination(dst
), depth
, index
, globalObject
);
715 emitPreIncOrDec(generator
, propDst
.get(), m_operator
);
716 generator
.emitPutScopedVar(depth
, index
, propDst
.get(), globalObject
);
717 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
720 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
721 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
722 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), propDst
.get(), m_ident
);
723 emitPreIncOrDec(generator
, propDst
.get(), m_operator
);
724 generator
.emitPutById(base
.get(), m_ident
, propDst
.get());
725 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
728 // ------------------------------ PrefixBracketNode ----------------------------------
730 RegisterID
* PrefixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
732 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
733 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
734 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
736 generator
.emitExpressionInfo(divot() + m_subexpressionDivotOffset
, m_subexpressionStartOffset
, endOffset() - m_subexpressionDivotOffset
);
737 RegisterID
* value
= generator
.emitGetByVal(propDst
.get(), base
.get(), property
.get());
738 if (m_operator
== OpPlusPlus
)
739 generator
.emitPreInc(value
);
741 generator
.emitPreDec(value
);
742 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
743 generator
.emitPutByVal(base
.get(), property
.get(), value
);
744 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
747 // ------------------------------ PrefixDotNode ----------------------------------
749 RegisterID
* PrefixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
751 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
752 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
754 generator
.emitExpressionInfo(divot() + m_subexpressionDivotOffset
, m_subexpressionStartOffset
, endOffset() - m_subexpressionDivotOffset
);
755 RegisterID
* value
= generator
.emitGetById(propDst
.get(), base
.get(), m_ident
);
756 if (m_operator
== OpPlusPlus
)
757 generator
.emitPreInc(value
);
759 generator
.emitPreDec(value
);
760 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
761 generator
.emitPutById(base
.get(), m_ident
, value
);
762 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
765 // ------------------------------ PrefixErrorNode -----------------------------------
767 RegisterID
* PrefixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
769 return emitThrowError(generator
, ReferenceError
, m_operator
== OpPlusPlus
770 ? "Prefix ++ operator applied to value that is not a reference."
771 : "Prefix -- operator applied to value that is not a reference.");
774 // ------------------------------ Unary Operation Nodes -----------------------------------
776 RegisterID
* UnaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
778 RegisterID
* src
= generator
.emitNode(m_expr
);
779 return generator
.emitUnaryOp(opcodeID(), generator
.finalDestination(dst
), src
);
783 // ------------------------------ LogicalNotNode -----------------------------------
785 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
787 ASSERT(expr()->hasConditionContextCodegen());
789 // reverse the true and false targets
790 generator
.emitNodeInConditionContext(expr(), falseTarget
, trueTarget
, !fallThroughMeansTrue
);
794 // ------------------------------ Binary Operation Nodes -----------------------------------
796 // BinaryOpNode::emitStrcat:
798 // This node generates an op_strcat operation. This opcode can handle concatenation of three or
799 // more values, where we can determine a set of separate op_add operations would be operating on
802 // This function expects to be operating on a graph of AST nodes looking something like this:
812 // The assignment operation is optional, if it exists the register holding the value on the
813 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
815 // The method should be called on the node at the root of the tree of regular binary add
816 // operations (marked in the diagram with a double set of parentheses). This node must
817 // be performing a string concatenation (determined by statically detecting that at least
818 // one child must be a string).
820 // Since the minimum number of values being concatenated together is expected to be 3, if
821 // a lhs to a concatenating assignment is not provided then the root add should have at
822 // least one left child that is also an add that can be determined to be operating on strings.
824 RegisterID
* BinaryOpNode::emitStrcat(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* lhs
, ReadModifyResolveNode
* emitExpressionInfoForMe
)
827 ASSERT(resultDescriptor().definitelyIsString());
829 // Create a list of expressions for all the adds in the tree of nodes we can convert into
830 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
831 // added first, and the leftmost child is never added, so the vector produced for the
832 // example above will be [ c, b ].
833 Vector
<ExpressionNode
*, 16> reverseExpressionList
;
834 reverseExpressionList
.append(m_expr2
);
836 // Examine the left child of the add. So long as this is a string add, add its right-child
837 // to the list, and keep processing along the left fork.
838 ExpressionNode
* leftMostAddChild
= m_expr1
;
839 while (leftMostAddChild
->isAdd() && leftMostAddChild
->resultDescriptor().definitelyIsString()) {
840 reverseExpressionList
.append(static_cast<AddNode
*>(leftMostAddChild
)->m_expr2
);
841 leftMostAddChild
= static_cast<AddNode
*>(leftMostAddChild
)->m_expr1
;
844 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
846 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
847 // We could possibly avoid this (the lhs is converted last anyway, we could let the
848 // op_strcat node handle its conversion if required).
850 temporaryRegisters
.append(generator
.newTemporary());
852 // Emit code for the leftmost node ((a) in the example).
853 temporaryRegisters
.append(generator
.newTemporary());
854 RegisterID
* leftMostAddChildTempRegister
= temporaryRegisters
.last().get();
855 generator
.emitNode(leftMostAddChildTempRegister
, leftMostAddChild
);
857 // Note on ordering of conversions:
859 // We maintain the same ordering of conversions as we would see if the concatenations
860 // was performed as a sequence of adds (otherwise this optimization could change
861 // behaviour should an object have been provided a valueOf or toString method).
863 // Considering the above example, the sequnce of execution is:
864 // * evaluate operand (a)
865 // * evaluate operand (b)
866 // * convert (a) to primitive <- (this would be triggered by the first add)
867 // * convert (b) to primitive <- (ditto)
868 // * evaluate operand (c)
869 // * convert (c) to primitive <- (this would be triggered by the second add)
870 // And optionally, if there is an assignment:
871 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
873 // As such we do not plant an op to convert the leftmost child now. Instead, use
874 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
875 // once the second node has been generated. However, if the leftmost child is an
876 // immediate we can trivially determine that no conversion will be required.
877 // If this is the case
878 if (leftMostAddChild
->isString())
879 leftMostAddChildTempRegister
= 0;
881 while (reverseExpressionList
.size()) {
882 ExpressionNode
* node
= reverseExpressionList
.last();
883 reverseExpressionList
.removeLast();
885 // Emit the code for the current node.
886 temporaryRegisters
.append(generator
.newTemporary());
887 generator
.emitNode(temporaryRegisters
.last().get(), node
);
889 // On the first iteration of this loop, when we first reach this point we have just
890 // generated the second node, which means it is time to convert the leftmost operand.
891 if (leftMostAddChildTempRegister
) {
892 generator
.emitToPrimitive(leftMostAddChildTempRegister
, leftMostAddChildTempRegister
);
893 leftMostAddChildTempRegister
= 0; // Only do this once.
895 // Plant a conversion for this node, if necessary.
896 if (!node
->isString())
897 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
899 ASSERT(temporaryRegisters
.size() >= 3);
901 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
902 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
903 if (emitExpressionInfoForMe
)
904 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
906 // If there is an assignment convert the lhs now. This will also copy lhs to
907 // the temporary register we allocated for it.
909 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
911 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
914 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
916 OpcodeID opcodeID
= this->opcodeID();
918 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString())
919 return emitStrcat(generator
, dst
);
921 if (opcodeID
== op_neq
) {
922 if (m_expr1
->isNull() || m_expr2
->isNull()) {
923 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
924 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
925 return generator
.emitUnaryOp(op_neq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
929 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
930 RegisterID
* src2
= generator
.emitNode(m_expr2
);
931 return generator
.emitBinaryOp(opcodeID
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
934 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
936 if (m_expr1
->isNull() || m_expr2
->isNull()) {
937 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
938 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
939 return generator
.emitUnaryOp(op_eq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
942 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
943 RegisterID
* src2
= generator
.emitNode(m_expr2
);
944 return generator
.emitEqualityOp(op_eq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
947 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
949 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
950 RegisterID
* src2
= generator
.emitNode(m_expr2
);
951 return generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
954 RegisterID
* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
956 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
957 RegisterID
* src2
= generator
.emitNode(m_expr2
);
958 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src2
, src1
.get(), OperandTypes(m_expr2
->resultDescriptor(), m_expr1
->resultDescriptor()));
961 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
963 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
964 RegisterID
* src2
= generator
.emitNode(m_expr2
);
965 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
966 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
969 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
971 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
972 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
974 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
975 generator
.emitGetByIdExceptionInfo(op_instanceof
);
976 RegisterID
* src2Prototype
= generator
.emitGetById(generator
.newTemporary(), src2
.get(), generator
.globalData()->propertyNames
->prototype
);
978 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
979 return generator
.emitInstanceOf(generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), src2Prototype
);
982 // ------------------------------ LogicalOpNode ----------------------------
984 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
986 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
987 RefPtr
<Label
> target
= generator
.newLabel();
989 generator
.emitNode(temp
.get(), m_expr1
);
990 if (m_operator
== OpLogicalAnd
)
991 generator
.emitJumpIfFalse(temp
.get(), target
.get());
993 generator
.emitJumpIfTrue(temp
.get(), target
.get());
994 generator
.emitNode(temp
.get(), m_expr2
);
995 generator
.emitLabel(target
.get());
997 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
1000 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
1002 if (m_expr1
->hasConditionContextCodegen()) {
1003 RefPtr
<Label
> afterExpr1
= generator
.newLabel();
1004 if (m_operator
== OpLogicalAnd
)
1005 generator
.emitNodeInConditionContext(m_expr1
, afterExpr1
.get(), falseTarget
, true);
1007 generator
.emitNodeInConditionContext(m_expr1
, trueTarget
, afterExpr1
.get(), false);
1008 generator
.emitLabel(afterExpr1
.get());
1010 RegisterID
* temp
= generator
.emitNode(m_expr1
);
1011 if (m_operator
== OpLogicalAnd
)
1012 generator
.emitJumpIfFalse(temp
, falseTarget
);
1014 generator
.emitJumpIfTrue(temp
, trueTarget
);
1017 if (m_expr2
->hasConditionContextCodegen())
1018 generator
.emitNodeInConditionContext(m_expr2
, trueTarget
, falseTarget
, fallThroughMeansTrue
);
1020 RegisterID
* temp
= generator
.emitNode(m_expr2
);
1021 if (fallThroughMeansTrue
)
1022 generator
.emitJumpIfFalse(temp
, falseTarget
);
1024 generator
.emitJumpIfTrue(temp
, trueTarget
);
1028 // ------------------------------ ConditionalNode ------------------------------
1030 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1032 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
1033 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1034 RefPtr
<Label
> afterElse
= generator
.newLabel();
1036 if (m_logical
->hasConditionContextCodegen()) {
1037 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1038 generator
.emitNodeInConditionContext(m_logical
, beforeThen
.get(), beforeElse
.get(), true);
1039 generator
.emitLabel(beforeThen
.get());
1041 RegisterID
* cond
= generator
.emitNode(m_logical
);
1042 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1045 generator
.emitNode(newDst
.get(), m_expr1
);
1046 generator
.emitJump(afterElse
.get());
1048 generator
.emitLabel(beforeElse
.get());
1049 generator
.emitNode(newDst
.get(), m_expr2
);
1051 generator
.emitLabel(afterElse
.get());
1053 return newDst
.get();
1056 // ------------------------------ ReadModifyResolveNode -----------------------------------
1058 // FIXME: should this be moved to be a method on BytecodeGenerator?
1059 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1070 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1071 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1078 opcodeID
= op_lshift
;
1081 opcodeID
= op_rshift
;
1084 opcodeID
= op_urshift
;
1087 opcodeID
= op_bitand
;
1090 opcodeID
= op_bitxor
;
1093 opcodeID
= op_bitor
;
1099 ASSERT_NOT_REACHED();
1103 RegisterID
* src2
= generator
.emitNode(m_right
);
1105 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1106 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1107 if (emitExpressionInfoForMe
)
1108 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
1110 return generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1113 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1115 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1116 if (generator
.isLocalConstant(m_ident
)) {
1117 return emitReadModifyAssignment(generator
, generator
.finalDestination(dst
), local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1120 if (generator
.leftHandSideNeedsCopy(m_rightHasAssignments
, m_right
->isPure(generator
))) {
1121 RefPtr
<RegisterID
> result
= generator
.newTemporary();
1122 generator
.emitMove(result
.get(), local
);
1123 emitReadModifyAssignment(generator
, result
.get(), result
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1124 generator
.emitMove(local
, result
.get());
1125 return generator
.moveToDestinationIfNeeded(dst
, result
.get());
1128 RegisterID
* result
= emitReadModifyAssignment(generator
, local
, local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1129 return generator
.moveToDestinationIfNeeded(dst
, result
);
1134 JSObject
* globalObject
= 0;
1135 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, globalObject
) && index
!= missingSymbolMarker()) {
1136 RefPtr
<RegisterID
> src1
= generator
.emitGetScopedVar(generator
.tempDestination(dst
), depth
, index
, globalObject
);
1137 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1138 generator
.emitPutScopedVar(depth
, index
, result
, globalObject
);
1142 RefPtr
<RegisterID
> src1
= generator
.tempDestination(dst
);
1143 generator
.emitExpressionInfo(divot() - startOffset() + m_ident
.size(), m_ident
.size(), 0);
1144 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), src1
.get(), m_ident
);
1145 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()), this);
1146 return generator
.emitPutById(base
.get(), m_ident
, result
);
1149 // ------------------------------ AssignResolveNode -----------------------------------
1151 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1153 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1154 if (generator
.isLocalConstant(m_ident
))
1155 return generator
.emitNode(dst
, m_right
);
1157 RegisterID
* result
= generator
.emitNode(local
, m_right
);
1158 return generator
.moveToDestinationIfNeeded(dst
, result
);
1163 JSObject
* globalObject
= 0;
1164 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, globalObject
) && index
!= missingSymbolMarker()) {
1165 if (dst
== generator
.ignoredResult())
1167 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1168 generator
.emitPutScopedVar(depth
, index
, value
, globalObject
);
1172 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1173 if (dst
== generator
.ignoredResult())
1175 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1176 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1177 return generator
.emitPutById(base
.get(), m_ident
, value
);
1180 // ------------------------------ AssignDotNode -----------------------------------
1182 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1184 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1185 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1186 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1187 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1188 generator
.emitPutById(base
.get(), m_ident
, result
);
1189 return generator
.moveToDestinationIfNeeded(dst
, result
);
1192 // ------------------------------ ReadModifyDotNode -----------------------------------
1194 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1196 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1198 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1199 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
1200 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1202 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1203 return generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1206 // ------------------------------ AssignErrorNode -----------------------------------
1208 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1210 return emitThrowError(generator
, ReferenceError
, "Left side of assignment is not a reference.");
1213 // ------------------------------ AssignBracketNode -----------------------------------
1215 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1217 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1218 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1219 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1220 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1222 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1223 generator
.emitPutByVal(base
.get(), property
.get(), result
);
1224 return generator
.moveToDestinationIfNeeded(dst
, result
);
1227 // ------------------------------ ReadModifyBracketNode -----------------------------------
1229 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1231 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1232 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1234 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1235 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
1236 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1238 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1239 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1241 return updatedValue
;
1244 // ------------------------------ CommaNode ------------------------------------
1246 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1248 ASSERT(m_expressions
.size() > 1);
1249 for (size_t i
= 0; i
< m_expressions
.size() - 1; i
++)
1250 generator
.emitNode(generator
.ignoredResult(), m_expressions
[i
]);
1251 return generator
.emitNode(dst
, m_expressions
.last());
1254 // ------------------------------ ConstDeclNode ------------------------------------
1256 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1258 if (RegisterID
* local
= generator
.constRegisterFor(m_ident
)) {
1262 return generator
.emitNode(local
, m_init
);
1265 if (generator
.codeType() != EvalCode
) {
1267 return generator
.emitNode(m_init
);
1269 return generator
.emitResolve(generator
.newTemporary(), m_ident
);
1271 // FIXME: While this code should only be hit in eval code, it will potentially
1272 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1273 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1274 RegisterID
* value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1275 return generator
.emitPutById(base
.get(), m_ident
, value
);
1278 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1280 RegisterID
* result
= 0;
1281 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1282 result
= n
->emitCodeSingle(generator
);
1287 // ------------------------------ ConstStatementNode -----------------------------
1289 RegisterID
* ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1291 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1292 return generator
.emitNode(m_next
);
1295 // ------------------------------ SourceElements -------------------------------
1298 inline StatementNode
* SourceElements::lastStatement() const
1300 size_t size
= m_statements
.size();
1301 return size
? m_statements
[size
- 1] : 0;
1304 inline void SourceElements::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1306 size_t size
= m_statements
.size();
1307 for (size_t i
= 0; i
< size
; ++i
)
1308 generator
.emitNode(dst
, m_statements
[i
]);
1311 // ------------------------------ BlockNode ------------------------------------
1313 inline StatementNode
* BlockNode::lastStatement() const
1315 return m_statements
? m_statements
->lastStatement() : 0;
1318 RegisterID
* BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1321 m_statements
->emitBytecode(generator
, dst
);
1325 // ------------------------------ EmptyStatementNode ---------------------------
1327 RegisterID
* EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1329 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1333 // ------------------------------ DebuggerStatementNode ---------------------------
1335 RegisterID
* DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1337 generator
.emitDebugHook(DidReachBreakpoint
, firstLine(), lastLine());
1341 // ------------------------------ ExprStatementNode ----------------------------
1343 RegisterID
* ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1346 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1347 return generator
.emitNode(dst
, m_expr
);
1350 // ------------------------------ VarStatementNode ----------------------------
1352 RegisterID
* VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1355 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1356 return generator
.emitNode(m_expr
);
1359 // ------------------------------ IfNode ---------------------------------------
1361 RegisterID
* IfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1363 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1365 RefPtr
<Label
> afterThen
= generator
.newLabel();
1367 if (m_condition
->hasConditionContextCodegen()) {
1368 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1369 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), afterThen
.get(), true);
1370 generator
.emitLabel(beforeThen
.get());
1372 RegisterID
* cond
= generator
.emitNode(m_condition
);
1373 generator
.emitJumpIfFalse(cond
, afterThen
.get());
1376 generator
.emitNode(dst
, m_ifBlock
);
1377 generator
.emitLabel(afterThen
.get());
1379 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1383 // ------------------------------ IfElseNode ---------------------------------------
1385 RegisterID
* IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1387 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1389 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1390 RefPtr
<Label
> afterElse
= generator
.newLabel();
1392 if (m_condition
->hasConditionContextCodegen()) {
1393 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1394 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), beforeElse
.get(), true);
1395 generator
.emitLabel(beforeThen
.get());
1397 RegisterID
* cond
= generator
.emitNode(m_condition
);
1398 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1401 generator
.emitNode(dst
, m_ifBlock
);
1402 generator
.emitJump(afterElse
.get());
1404 generator
.emitLabel(beforeElse
.get());
1406 generator
.emitNode(dst
, m_elseBlock
);
1408 generator
.emitLabel(afterElse
.get());
1410 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1414 // ------------------------------ DoWhileNode ----------------------------------
1416 RegisterID
* DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1418 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1420 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1421 generator
.emitLabel(topOfLoop
.get());
1423 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1425 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1427 generator
.emitLabel(scope
->continueTarget());
1428 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1429 if (m_expr
->hasConditionContextCodegen())
1430 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1432 RegisterID
* cond
= generator
.emitNode(m_expr
);
1433 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1436 generator
.emitLabel(scope
->breakTarget());
1437 return result
.get();
1440 // ------------------------------ WhileNode ------------------------------------
1442 RegisterID
* WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1444 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1446 generator
.emitJump(scope
->continueTarget());
1448 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1449 generator
.emitLabel(topOfLoop
.get());
1451 generator
.emitNode(dst
, m_statement
);
1453 generator
.emitLabel(scope
->continueTarget());
1454 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1456 if (m_expr
->hasConditionContextCodegen())
1457 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1459 RegisterID
* cond
= generator
.emitNode(m_expr
);
1460 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1463 generator
.emitLabel(scope
->breakTarget());
1465 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1469 // ------------------------------ ForNode --------------------------------------
1471 RegisterID
* ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1473 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1475 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1478 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
1480 RefPtr
<Label
> condition
= generator
.newLabel();
1481 generator
.emitJump(condition
.get());
1483 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1484 generator
.emitLabel(topOfLoop
.get());
1486 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1488 generator
.emitLabel(scope
->continueTarget());
1489 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1491 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
1493 generator
.emitLabel(condition
.get());
1495 if (m_expr2
->hasConditionContextCodegen())
1496 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), false);
1498 RegisterID
* cond
= generator
.emitNode(m_expr2
);
1499 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1502 generator
.emitJump(topOfLoop
.get());
1504 generator
.emitLabel(scope
->breakTarget());
1505 return result
.get();
1508 // ------------------------------ ForInNode ------------------------------------
1510 RegisterID
* ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1512 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1514 if (!m_lexpr
->isLocation())
1515 return emitThrowError(generator
, ReferenceError
, "Left side of for-in statement is not a reference.");
1517 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1520 generator
.emitNode(generator
.ignoredResult(), m_init
);
1522 RefPtr
<RegisterID
> base
= generator
.newTemporary();
1523 generator
.emitNode(base
.get(), m_expr
);
1524 RefPtr
<RegisterID
> i
= generator
.newTemporary();
1525 RefPtr
<RegisterID
> size
= generator
.newTemporary();
1526 RefPtr
<RegisterID
> expectedSubscript
;
1527 RefPtr
<RegisterID
> iter
= generator
.emitGetPropertyNames(generator
.newTemporary(), base
.get(), i
.get(), size
.get(), scope
->breakTarget());
1528 generator
.emitJump(scope
->continueTarget());
1530 RefPtr
<Label
> loopStart
= generator
.newLabel();
1531 generator
.emitLabel(loopStart
.get());
1533 RegisterID
* propertyName
;
1534 bool optimizedForinAccess
= false;
1535 if (m_lexpr
->isResolveNode()) {
1536 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1537 propertyName
= generator
.registerFor(ident
);
1538 if (!propertyName
) {
1539 propertyName
= generator
.newTemporary();
1540 RefPtr
<RegisterID
> protect
= propertyName
;
1541 RegisterID
* base
= generator
.emitResolveBase(generator
.newTemporary(), ident
);
1543 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1544 generator
.emitPutById(base
, ident
, propertyName
);
1546 expectedSubscript
= generator
.emitMove(generator
.newTemporary(), propertyName
);
1547 generator
.pushOptimisedForIn(expectedSubscript
.get(), iter
.get(), i
.get(), propertyName
);
1548 optimizedForinAccess
= true;
1550 } else if (m_lexpr
->isDotAccessorNode()) {
1551 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1552 const Identifier
& ident
= assignNode
->identifier();
1553 propertyName
= generator
.newTemporary();
1554 RefPtr
<RegisterID
> protect
= propertyName
;
1555 RegisterID
* base
= generator
.emitNode(assignNode
->base());
1557 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1558 generator
.emitPutById(base
, ident
, propertyName
);
1560 ASSERT(m_lexpr
->isBracketAccessorNode());
1561 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1562 propertyName
= generator
.newTemporary();
1563 RefPtr
<RegisterID
> protect
= propertyName
;
1564 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1565 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1567 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1568 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
1571 generator
.emitNode(dst
, m_statement
);
1573 if (optimizedForinAccess
)
1574 generator
.popOptimisedForIn();
1576 generator
.emitLabel(scope
->continueTarget());
1577 generator
.emitNextPropertyName(propertyName
, base
.get(), i
.get(), size
.get(), iter
.get(), loopStart
.get());
1578 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1579 generator
.emitLabel(scope
->breakTarget());
1583 // ------------------------------ ContinueNode ---------------------------------
1586 RegisterID
* ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1588 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1590 LabelScope
* scope
= generator
.continueTarget(m_ident
);
1593 return m_ident
.isEmpty()
1594 ? emitThrowError(generator
, SyntaxError
, "Invalid continue statement.")
1595 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1597 generator
.emitJumpScopes(scope
->continueTarget(), scope
->scopeDepth());
1601 // ------------------------------ BreakNode ------------------------------------
1604 RegisterID
* BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1606 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1608 LabelScope
* scope
= generator
.breakTarget(m_ident
);
1611 return m_ident
.isEmpty()
1612 ? emitThrowError(generator
, SyntaxError
, "Invalid break statement.")
1613 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1615 generator
.emitJumpScopes(scope
->breakTarget(), scope
->scopeDepth());
1619 // ------------------------------ ReturnNode -----------------------------------
1621 RegisterID
* ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1623 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1624 if (generator
.codeType() != FunctionCode
)
1625 return emitThrowError(generator
, SyntaxError
, "Invalid return statement.");
1627 if (dst
== generator
.ignoredResult())
1629 RegisterID
* r0
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
1630 RefPtr
<RegisterID
> returnRegister
;
1631 if (generator
.scopeDepth()) {
1632 RefPtr
<Label
> l0
= generator
.newLabel();
1633 if (generator
.hasFinaliser() && !r0
->isTemporary()) {
1634 returnRegister
= generator
.emitMove(generator
.newTemporary(), r0
);
1635 r0
= returnRegister
.get();
1637 generator
.emitJumpScopes(l0
.get(), 0);
1638 generator
.emitLabel(l0
.get());
1640 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1641 return generator
.emitReturn(r0
);
1644 // ------------------------------ WithNode -------------------------------------
1646 RegisterID
* WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1648 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1650 RefPtr
<RegisterID
> scope
= generator
.newTemporary();
1651 generator
.emitNode(scope
.get(), m_expr
); // scope must be protected until popped
1652 generator
.emitExpressionInfo(m_divot
, m_expressionLength
, 0);
1653 generator
.emitPushScope(scope
.get());
1654 RegisterID
* result
= generator
.emitNode(dst
, m_statement
);
1655 generator
.emitPopScope();
1659 // ------------------------------ CaseClauseNode --------------------------------
1661 inline void CaseClauseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1664 m_statements
->emitBytecode(generator
, dst
);
1667 // ------------------------------ CaseBlockNode --------------------------------
1676 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
1678 for (; list
; list
= list
->getNext()) {
1679 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
1680 literalVector
.append(clauseExpression
);
1681 if (clauseExpression
->isNumber()) {
1682 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
1683 int32_t intVal
= static_cast<int32_t>(value
);
1684 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
1685 typeForTable
= SwitchNeither
;
1688 if (intVal
< min_num
)
1690 if (intVal
> max_num
)
1692 typeForTable
= SwitchNumber
;
1695 if (clauseExpression
->isString()) {
1696 if (typeForTable
& ~SwitchString
) {
1697 typeForTable
= SwitchNeither
;
1700 const UString
& value
= static_cast<StringNode
*>(clauseExpression
)->value().ustring();
1701 if (singleCharacterSwitch
&= value
.size() == 1) {
1702 int32_t intVal
= value
.rep()->data()[0];
1703 if (intVal
< min_num
)
1705 if (intVal
> max_num
)
1708 typeForTable
= SwitchString
;
1711 typeForTable
= SwitchNeither
;
1716 SwitchInfo::SwitchType
CaseBlockNode::tryOptimizedSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
1718 SwitchKind typeForTable
= SwitchUnset
;
1719 bool singleCharacterSwitch
= true;
1721 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1722 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1724 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
1725 return SwitchInfo::SwitchNone
;
1727 if (typeForTable
== SwitchNumber
) {
1728 int32_t range
= max_num
- min_num
;
1729 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1730 return SwitchInfo::SwitchImmediate
;
1731 return SwitchInfo::SwitchNone
;
1734 ASSERT(typeForTable
== SwitchString
);
1736 if (singleCharacterSwitch
) {
1737 int32_t range
= max_num
- min_num
;
1738 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1739 return SwitchInfo::SwitchCharacter
;
1742 return SwitchInfo::SwitchString
;
1745 RegisterID
* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
1747 RefPtr
<Label
> defaultLabel
;
1748 Vector
<RefPtr
<Label
>, 8> labelVector
;
1749 Vector
<ExpressionNode
*, 8> literalVector
;
1750 int32_t min_num
= std::numeric_limits
<int32_t>::max();
1751 int32_t max_num
= std::numeric_limits
<int32_t>::min();
1752 SwitchInfo::SwitchType switchType
= tryOptimizedSwitch(literalVector
, min_num
, max_num
);
1754 if (switchType
!= SwitchInfo::SwitchNone
) {
1755 // Prepare the various labels
1756 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
1757 labelVector
.append(generator
.newLabel());
1758 defaultLabel
= generator
.newLabel();
1759 generator
.beginSwitch(switchExpression
, switchType
);
1762 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1763 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1764 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1765 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1766 labelVector
.append(generator
.newLabel());
1767 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1770 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1771 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1772 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1773 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1774 labelVector
.append(generator
.newLabel());
1775 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1777 defaultLabel
= generator
.newLabel();
1778 generator
.emitJump(defaultLabel
.get());
1781 RegisterID
* result
= 0;
1784 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1785 generator
.emitLabel(labelVector
[i
++].get());
1786 list
->getClause()->emitBytecode(generator
, dst
);
1789 if (m_defaultClause
) {
1790 generator
.emitLabel(defaultLabel
.get());
1791 m_defaultClause
->emitBytecode(generator
, dst
);
1794 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1795 generator
.emitLabel(labelVector
[i
++].get());
1796 list
->getClause()->emitBytecode(generator
, dst
);
1798 if (!m_defaultClause
)
1799 generator
.emitLabel(defaultLabel
.get());
1801 ASSERT(i
== labelVector
.size());
1802 if (switchType
!= SwitchInfo::SwitchNone
) {
1803 ASSERT(labelVector
.size() == literalVector
.size());
1804 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
1809 // ------------------------------ SwitchNode -----------------------------------
1811 RegisterID
* SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1813 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1815 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Switch
);
1817 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
1818 RegisterID
* r1
= m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
1820 generator
.emitLabel(scope
->breakTarget());
1824 // ------------------------------ LabelNode ------------------------------------
1826 RegisterID
* LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1828 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1830 if (generator
.breakTarget(m_name
))
1831 return emitThrowError(generator
, SyntaxError
, "Duplicate label: %s.", m_name
);
1833 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
1834 RegisterID
* r0
= generator
.emitNode(dst
, m_statement
);
1836 generator
.emitLabel(scope
->breakTarget());
1840 // ------------------------------ ThrowNode ------------------------------------
1842 RegisterID
* ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1844 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1846 if (dst
== generator
.ignoredResult())
1848 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
1849 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1850 generator
.emitThrow(expr
.get());
1854 // ------------------------------ TryNode --------------------------------------
1856 RegisterID
* TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1858 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1859 // optimizer knows they may be jumped to from anywhere.
1861 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1863 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
1864 RefPtr
<Label
> finallyStart
;
1865 RefPtr
<RegisterID
> finallyReturnAddr
;
1866 if (m_finallyBlock
) {
1867 finallyStart
= generator
.newLabel();
1868 finallyReturnAddr
= generator
.newTemporary();
1869 generator
.pushFinallyContext(finallyStart
.get(), finallyReturnAddr
.get());
1872 generator
.emitLabel(tryStartLabel
.get());
1873 generator
.emitNode(dst
, m_tryBlock
);
1876 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
1878 // Normal path: jump over the catch block.
1879 generator
.emitJump(catchEndLabel
.get());
1881 // Uncaught exception path: the catch block.
1882 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1883 RefPtr
<RegisterID
> exceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1884 if (m_catchHasEval
) {
1885 RefPtr
<RegisterID
> dynamicScopeObject
= generator
.emitNewObject(generator
.newTemporary());
1886 generator
.emitPutById(dynamicScopeObject
.get(), m_exceptionIdent
, exceptionRegister
.get());
1887 generator
.emitMove(exceptionRegister
.get(), dynamicScopeObject
.get());
1888 generator
.emitPushScope(exceptionRegister
.get());
1890 generator
.emitPushNewScope(exceptionRegister
.get(), m_exceptionIdent
, exceptionRegister
.get());
1891 generator
.emitNode(dst
, m_catchBlock
);
1892 generator
.emitPopScope();
1893 generator
.emitLabel(catchEndLabel
.get());
1896 if (m_finallyBlock
) {
1897 generator
.popFinallyContext();
1898 // there may be important registers live at the time we jump
1899 // to a finally block (such as for a return or throw) so we
1900 // ref the highest register ever used as a conservative
1901 // approach to not clobbering anything important
1902 RefPtr
<RegisterID
> highestUsedRegister
= generator
.highestUsedRegister();
1903 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
1905 // Normal path: invoke the finally block, then jump over it.
1906 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1907 generator
.emitJump(finallyEndLabel
.get());
1909 // Uncaught exception path: invoke the finally block, then re-throw the exception.
1910 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1911 RefPtr
<RegisterID
> tempExceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1912 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1913 generator
.emitThrow(tempExceptionRegister
.get());
1915 // The finally block.
1916 generator
.emitLabel(finallyStart
.get());
1917 generator
.emitNode(dst
, m_finallyBlock
);
1918 generator
.emitSubroutineReturn(finallyReturnAddr
.get());
1920 generator
.emitLabel(finallyEndLabel
.get());
1926 // ------------------------------ ScopeNode -----------------------------
1928 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1930 if (m_data
->m_statements
)
1931 m_data
->m_statements
->emitBytecode(generator
, dst
);
1934 // ------------------------------ ProgramNode -----------------------------
1936 RegisterID
* ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1938 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1940 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1941 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1942 emitStatementsBytecode(generator
, dstRegister
.get());
1944 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1945 generator
.emitEnd(dstRegister
.get());
1949 // ------------------------------ EvalNode -----------------------------
1951 RegisterID
* EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1953 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1955 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1956 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1957 emitStatementsBytecode(generator
, dstRegister
.get());
1959 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1960 generator
.emitEnd(dstRegister
.get());
1964 // ------------------------------ FunctionBodyNode -----------------------------
1966 RegisterID
* FunctionBodyNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1968 generator
.emitDebugHook(DidEnterCallFrame
, firstLine(), lastLine());
1969 emitStatementsBytecode(generator
, generator
.ignoredResult());
1970 StatementNode
* singleStatement
= this->singleStatement();
1971 if (singleStatement
&& singleStatement
->isBlock()) {
1972 StatementNode
* lastStatementInBlock
= static_cast<BlockNode
*>(singleStatement
)->lastStatement();
1973 if (lastStatementInBlock
&& lastStatementInBlock
->isReturnNode())
1977 RegisterID
* r0
= generator
.emitLoad(0, jsUndefined());
1978 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1979 generator
.emitReturn(r0
);
1983 // ------------------------------ FuncDeclNode ---------------------------------
1985 RegisterID
* FuncDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1987 if (dst
== generator
.ignoredResult())
1992 // ------------------------------ FuncExprNode ---------------------------------
1994 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1996 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);