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 "RegExpCache.h"
43 #include "RegExpObject.h"
44 #include "SamplingTool.h"
45 #include <wtf/Assertions.h>
46 #include <wtf/RefCountedLeakCounter.h>
47 #include <wtf/Threading.h>
54 Details of the emitBytecode function.
56 Return value: The register holding the production's value.
57 dst: An optional parameter specifying the most efficient destination at
58 which to store the production's value. The callee must honor dst.
60 The dst argument provides for a crude form of copy propagation. For example,
73 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
76 // ------------------------------ ThrowableExpressionData --------------------------------
78 static void substitute(UString
& string
, const UString
& substring
)
80 unsigned position
= string
.find("%s");
81 ASSERT(position
!= UString::NotFound
);
82 string
= makeString(string
.substr(0, position
), substring
, string
.substr(position
+ 2));
85 RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType type
, const char* message
)
87 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
88 RegisterID
* exception
= generator
.emitNewError(generator
.newTemporary(), type
, jsString(generator
.globalData(), message
));
89 generator
.emitThrow(exception
);
93 RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType type
, const char* messageTemplate
, const UString
& label
)
95 UString message
= messageTemplate
;
96 substitute(message
, label
);
97 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
98 RegisterID
* exception
= generator
.emitNewError(generator
.newTemporary(), type
, jsString(generator
.globalData(), message
));
99 generator
.emitThrow(exception
);
103 inline RegisterID
* ThrowableExpressionData::emitThrowError(BytecodeGenerator
& generator
, ErrorType type
, const char* messageTemplate
, const Identifier
& label
)
105 return emitThrowError(generator
, type
, messageTemplate
, label
.ustring());
108 // ------------------------------ NullNode -------------------------------------
110 RegisterID
* NullNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
112 if (dst
== generator
.ignoredResult())
114 return generator
.emitLoad(dst
, jsNull());
117 // ------------------------------ BooleanNode ----------------------------------
119 RegisterID
* BooleanNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
121 if (dst
== generator
.ignoredResult())
123 return generator
.emitLoad(dst
, m_value
);
126 // ------------------------------ NumberNode -----------------------------------
128 RegisterID
* NumberNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
130 if (dst
== generator
.ignoredResult())
132 return generator
.emitLoad(dst
, m_value
);
135 // ------------------------------ StringNode -----------------------------------
137 RegisterID
* StringNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
139 if (dst
== generator
.ignoredResult())
141 return generator
.emitLoad(dst
, m_value
);
144 // ------------------------------ RegExpNode -----------------------------------
146 RegisterID
* RegExpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
148 RefPtr
<RegExp
> regExp
= generator
.globalData()->regExpCache()->lookupOrCreate(m_pattern
.ustring(), m_flags
.ustring());
149 if (!regExp
->isValid())
150 return emitThrowError(generator
, SyntaxError
, "Invalid regular expression: %s", regExp
->errorMessage());
151 if (dst
== generator
.ignoredResult())
153 return generator
.emitNewRegExp(generator
.finalDestination(dst
), regExp
.get());
156 // ------------------------------ ThisNode -------------------------------------
158 RegisterID
* ThisNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
160 if (dst
== generator
.ignoredResult())
162 return generator
.moveToDestinationIfNeeded(dst
, generator
.thisRegister());
165 // ------------------------------ ResolveNode ----------------------------------
167 bool ResolveNode::isPure(BytecodeGenerator
& generator
) const
169 return generator
.isLocal(m_ident
);
172 RegisterID
* ResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
174 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
175 if (dst
== generator
.ignoredResult())
177 return generator
.moveToDestinationIfNeeded(dst
, local
);
180 generator
.emitExpressionInfo(m_startOffset
+ m_ident
.size(), m_ident
.size(), 0);
181 return generator
.emitResolve(generator
.finalDestination(dst
), m_ident
);
184 // ------------------------------ ArrayNode ------------------------------------
186 RegisterID
* ArrayNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
188 // FIXME: Should we put all of this code into emitNewArray?
191 ElementNode
* firstPutElement
;
192 for (firstPutElement
= m_element
; firstPutElement
; firstPutElement
= firstPutElement
->next()) {
193 if (firstPutElement
->elision())
198 if (!firstPutElement
&& !m_elision
)
199 return generator
.emitNewArray(generator
.finalDestination(dst
), m_element
);
201 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.tempDestination(dst
), m_element
);
203 for (ElementNode
* n
= firstPutElement
; n
; n
= n
->next()) {
204 RegisterID
* value
= generator
.emitNode(n
->value());
205 length
+= n
->elision();
206 generator
.emitPutByIndex(array
.get(), length
++, value
);
210 RegisterID
* value
= generator
.emitLoad(0, jsNumber(generator
.globalData(), m_elision
+ length
));
211 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, value
);
214 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
217 bool ArrayNode::isSimpleArray() const
219 if (m_elision
|| m_optional
)
221 for (ElementNode
* ptr
= m_element
; ptr
; ptr
= ptr
->next()) {
228 ArgumentListNode
* ArrayNode::toArgumentList(JSGlobalData
* globalData
) const
230 ASSERT(!m_elision
&& !m_optional
);
231 ElementNode
* ptr
= m_element
;
234 ArgumentListNode
* head
= new (globalData
) ArgumentListNode(globalData
, ptr
->value());
235 ArgumentListNode
* tail
= head
;
237 for (; ptr
; ptr
= ptr
->next()) {
238 ASSERT(!ptr
->elision());
239 tail
= new (globalData
) ArgumentListNode(globalData
, tail
, ptr
->value());
244 // ------------------------------ ObjectLiteralNode ----------------------------
246 RegisterID
* ObjectLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
249 if (dst
== generator
.ignoredResult())
251 return generator
.emitNewObject(generator
.finalDestination(dst
));
253 return generator
.emitNode(dst
, m_list
);
256 // ------------------------------ PropertyListNode -----------------------------
258 RegisterID
* PropertyListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
260 RefPtr
<RegisterID
> newObj
= generator
.tempDestination(dst
);
262 generator
.emitNewObject(newObj
.get());
264 for (PropertyListNode
* p
= this; p
; p
= p
->m_next
) {
265 RegisterID
* value
= generator
.emitNode(p
->m_node
->m_assign
);
267 switch (p
->m_node
->m_type
) {
268 case PropertyNode::Constant
: {
269 generator
.emitDirectPutById(newObj
.get(), p
->m_node
->name(), value
);
272 case PropertyNode::Getter
: {
273 generator
.emitPutGetter(newObj
.get(), p
->m_node
->name(), value
);
276 case PropertyNode::Setter
: {
277 generator
.emitPutSetter(newObj
.get(), p
->m_node
->name(), value
);
281 ASSERT_NOT_REACHED();
285 return generator
.moveToDestinationIfNeeded(dst
, newObj
.get());
288 // ------------------------------ BracketAccessorNode --------------------------------
290 RegisterID
* BracketAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
292 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
, m_subscript
->isPure(generator
));
293 RegisterID
* property
= generator
.emitNode(m_subscript
);
294 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
295 return generator
.emitGetByVal(generator
.finalDestination(dst
), base
.get(), property
);
298 // ------------------------------ DotAccessorNode --------------------------------
300 RegisterID
* DotAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
302 RegisterID
* base
= generator
.emitNode(m_base
);
303 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
304 return generator
.emitGetById(generator
.finalDestination(dst
), base
, m_ident
);
307 // ------------------------------ ArgumentListNode -----------------------------
309 RegisterID
* ArgumentListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
312 return generator
.emitNode(dst
, m_expr
);
315 // ------------------------------ NewExprNode ----------------------------------
317 RegisterID
* NewExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
319 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
320 return generator
.emitConstruct(generator
.finalDestination(dst
), func
.get(), m_args
, divot(), startOffset(), endOffset());
323 // ------------------------------ EvalFunctionCallNode ----------------------------------
325 RegisterID
* EvalFunctionCallNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
327 RefPtr
<RegisterID
> func
= generator
.tempDestination(dst
);
328 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
329 generator
.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
330 generator
.emitResolveWithBase(thisRegister
.get(), func
.get(), generator
.propertyNames().eval
);
331 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
334 // ------------------------------ FunctionCallValueNode ----------------------------------
336 RegisterID
* FunctionCallValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
338 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
339 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsNull());
340 return generator
.emitCall(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
343 // ------------------------------ FunctionCallResolveNode ----------------------------------
345 RegisterID
* FunctionCallResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
347 if (RefPtr
<RegisterID
> local
= generator
.registerFor(m_ident
)) {
348 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsNull());
349 return generator
.emitCall(generator
.finalDestination(dst
, thisRegister
.get()), local
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
354 JSObject
* globalObject
= 0;
355 bool requiresDynamicChecks
= false;
356 if (generator
.findScopedProperty(m_ident
, index
, depth
, false, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
357 RefPtr
<RegisterID
> func
= generator
.emitGetScopedVar(generator
.newTemporary(), depth
, index
, globalObject
);
358 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsNull());
359 return generator
.emitCall(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
362 RefPtr
<RegisterID
> func
= generator
.newTemporary();
363 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
364 int identifierStart
= divot() - startOffset();
365 generator
.emitExpressionInfo(identifierStart
+ m_ident
.size(), m_ident
.size(), 0);
366 generator
.emitResolveWithBase(thisRegister
.get(), func
.get(), m_ident
);
367 return generator
.emitCall(generator
.finalDestination(dst
, func
.get()), func
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
370 // ------------------------------ FunctionCallBracketNode ----------------------------------
372 RegisterID
* FunctionCallBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
374 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
375 RegisterID
* property
= generator
.emitNode(m_subscript
);
376 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
377 RefPtr
<RegisterID
> function
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
);
378 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
379 return generator
.emitCall(generator
.finalDestination(dst
, function
.get()), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
382 // ------------------------------ FunctionCallDotNode ----------------------------------
384 RegisterID
* FunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
386 RefPtr
<RegisterID
> function
= generator
.tempDestination(dst
);
387 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
388 generator
.emitNode(thisRegister
.get(), m_base
);
389 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
390 generator
.emitMethodCheck();
391 generator
.emitGetById(function
.get(), thisRegister
.get(), m_ident
);
392 return generator
.emitCall(generator
.finalDestination(dst
, function
.get()), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
395 RegisterID
* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
397 RefPtr
<Label
> realCall
= generator
.newLabel();
398 RefPtr
<Label
> end
= generator
.newLabel();
399 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
400 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
401 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
402 RefPtr
<RegisterID
> finalDestination
= generator
.finalDestination(dst
, function
.get());
403 generator
.emitJumpIfNotFunctionCall(function
.get(), realCall
.get());
405 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
406 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
407 ArgumentListNode
* oldList
= m_args
->m_listNode
;
408 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
409 generator
.emitNode(thisRegister
.get(), m_args
->m_listNode
->m_expr
);
410 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
412 generator
.emitLoad(thisRegister
.get(), jsNull());
414 generator
.emitCall(finalDestination
.get(), realFunction
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
415 generator
.emitJump(end
.get());
416 m_args
->m_listNode
= oldList
;
418 generator
.emitLabel(realCall
.get());
420 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
421 generator
.emitCall(finalDestination
.get(), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
423 generator
.emitLabel(end
.get());
424 return finalDestination
.get();
427 static bool areTrivialApplyArguments(ArgumentsNode
* args
)
429 return !args
->m_listNode
|| !args
->m_listNode
->m_expr
|| !args
->m_listNode
->m_next
430 || (!args
->m_listNode
->m_next
->m_next
&& args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
433 RegisterID
* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
435 // A few simple cases can be trivially handled as ordinary function calls.
436 // function.apply(), function.apply(arg) -> identical to function.call
437 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
438 bool mayBeCall
= areTrivialApplyArguments(m_args
);
440 RefPtr
<Label
> realCall
= generator
.newLabel();
441 RefPtr
<Label
> end
= generator
.newLabel();
442 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
443 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
444 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
445 RefPtr
<RegisterID
> finalDestination
= generator
.finalDestination(dst
, function
.get());
446 generator
.emitJumpIfNotFunctionApply(function
.get(), realCall
.get());
449 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
450 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
451 ArgumentListNode
* oldList
= m_args
->m_listNode
;
452 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
453 generator
.emitNode(thisRegister
.get(), m_args
->m_listNode
->m_expr
);
454 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
455 if (m_args
->m_listNode
) {
456 ASSERT(m_args
->m_listNode
->m_expr
->isSimpleArray());
457 ASSERT(!m_args
->m_listNode
->m_next
);
458 m_args
->m_listNode
= static_cast<ArrayNode
*>(m_args
->m_listNode
->m_expr
)->toArgumentList(generator
.globalData());
461 generator
.emitLoad(thisRegister
.get(), jsNull());
462 generator
.emitCall(finalDestination
.get(), realFunction
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
463 m_args
->m_listNode
= oldList
;
465 ASSERT(m_args
->m_listNode
&& m_args
->m_listNode
->m_next
);
466 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.newTemporary(), base
.get());
467 RefPtr
<RegisterID
> argsCountRegister
= generator
.newTemporary();
468 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
469 RefPtr
<RegisterID
> argsRegister
= generator
.newTemporary();
470 generator
.emitNode(thisRegister
.get(), m_args
->m_listNode
->m_expr
);
471 ArgumentListNode
* args
= m_args
->m_listNode
->m_next
;
472 bool isArgumentsApply
= false;
473 if (args
->m_expr
->isResolveNode()) {
474 ResolveNode
* resolveNode
= static_cast<ResolveNode
*>(args
->m_expr
);
475 isArgumentsApply
= generator
.willResolveToArguments(resolveNode
->identifier());
476 if (isArgumentsApply
)
477 generator
.emitMove(argsRegister
.get(), generator
.uncheckedRegisterForArguments());
479 if (!isArgumentsApply
)
480 generator
.emitNode(argsRegister
.get(), args
->m_expr
);
481 while ((args
= args
->m_next
))
482 generator
.emitNode(args
->m_expr
);
484 generator
.emitLoadVarargs(argsCountRegister
.get(), argsRegister
.get());
485 generator
.emitCallVarargs(finalDestination
.get(), realFunction
.get(), thisRegister
.get(), argsCountRegister
.get(), divot(), startOffset(), endOffset());
487 generator
.emitJump(end
.get());
489 generator
.emitLabel(realCall
.get());
491 RefPtr
<RegisterID
> thisRegister
= generator
.emitMove(generator
.newTemporary(), base
.get());
492 generator
.emitCall(finalDestination
.get(), function
.get(), thisRegister
.get(), m_args
, divot(), startOffset(), endOffset());
494 generator
.emitLabel(end
.get());
495 return finalDestination
.get();
498 // ------------------------------ PostfixResolveNode ----------------------------------
500 static RegisterID
* emitPreIncOrDec(BytecodeGenerator
& generator
, RegisterID
* srcDst
, Operator oper
)
502 return (oper
== OpPlusPlus
) ? generator
.emitPreInc(srcDst
) : generator
.emitPreDec(srcDst
);
505 static RegisterID
* emitPostIncOrDec(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* srcDst
, Operator oper
)
508 return generator
.emitToJSNumber(dst
, srcDst
);
509 return (oper
== OpPlusPlus
) ? generator
.emitPostInc(dst
, srcDst
) : generator
.emitPostDec(dst
, srcDst
);
512 RegisterID
* PostfixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
514 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
515 if (generator
.isLocalConstant(m_ident
)) {
516 if (dst
== generator
.ignoredResult())
518 return generator
.emitToJSNumber(generator
.finalDestination(dst
), local
);
521 if (dst
== generator
.ignoredResult())
522 return emitPreIncOrDec(generator
, local
, m_operator
);
523 return emitPostIncOrDec(generator
, generator
.finalDestination(dst
), local
, m_operator
);
528 JSObject
* globalObject
= 0;
529 bool requiresDynamicChecks
= false;
530 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
531 RefPtr
<RegisterID
> value
= generator
.emitGetScopedVar(generator
.newTemporary(), depth
, index
, globalObject
);
532 RegisterID
* oldValue
;
533 if (dst
== generator
.ignoredResult()) {
535 emitPreIncOrDec(generator
, value
.get(), m_operator
);
537 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
539 generator
.emitPutScopedVar(depth
, index
, value
.get(), globalObject
);
543 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
544 RefPtr
<RegisterID
> value
= generator
.newTemporary();
545 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), value
.get(), m_ident
);
546 RegisterID
* oldValue
;
547 if (dst
== generator
.ignoredResult()) {
549 emitPreIncOrDec(generator
, value
.get(), m_operator
);
551 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
553 generator
.emitPutById(base
.get(), m_ident
, value
.get());
557 // ------------------------------ PostfixBracketNode ----------------------------------
559 RegisterID
* PostfixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
561 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
562 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
564 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
565 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.newTemporary(), base
.get(), property
.get());
566 RegisterID
* oldValue
;
567 if (dst
== generator
.ignoredResult()) {
569 if (m_operator
== OpPlusPlus
)
570 generator
.emitPreInc(value
.get());
572 generator
.emitPreDec(value
.get());
574 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
576 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
577 generator
.emitPutByVal(base
.get(), property
.get(), value
.get());
581 // ------------------------------ PostfixDotNode ----------------------------------
583 RegisterID
* PostfixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
585 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
587 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
588 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.newTemporary(), base
.get(), m_ident
);
589 RegisterID
* oldValue
;
590 if (dst
== generator
.ignoredResult()) {
592 if (m_operator
== OpPlusPlus
)
593 generator
.emitPreInc(value
.get());
595 generator
.emitPreDec(value
.get());
597 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
599 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
600 generator
.emitPutById(base
.get(), m_ident
, value
.get());
604 // ------------------------------ PostfixErrorNode -----------------------------------
606 RegisterID
* PostfixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
608 return emitThrowError(generator
, ReferenceError
, m_operator
== OpPlusPlus
609 ? "Postfix ++ operator applied to value that is not a reference."
610 : "Postfix -- operator applied to value that is not a reference.");
613 // ------------------------------ DeleteResolveNode -----------------------------------
615 RegisterID
* DeleteResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
617 if (generator
.registerFor(m_ident
))
618 return generator
.emitLoad(generator
.finalDestination(dst
), false);
620 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
621 RegisterID
* base
= generator
.emitResolveBase(generator
.tempDestination(dst
), m_ident
);
622 return generator
.emitDeleteById(generator
.finalDestination(dst
, base
), base
, m_ident
);
625 // ------------------------------ DeleteBracketNode -----------------------------------
627 RegisterID
* DeleteBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
629 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
630 RegisterID
* r1
= generator
.emitNode(m_subscript
);
632 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
633 return generator
.emitDeleteByVal(generator
.finalDestination(dst
), r0
.get(), r1
);
636 // ------------------------------ DeleteDotNode -----------------------------------
638 RegisterID
* DeleteDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
640 RegisterID
* r0
= generator
.emitNode(m_base
);
642 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
643 return generator
.emitDeleteById(generator
.finalDestination(dst
), r0
, m_ident
);
646 // ------------------------------ DeleteValueNode -----------------------------------
648 RegisterID
* DeleteValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
650 generator
.emitNode(generator
.ignoredResult(), m_expr
);
652 // delete on a non-location expression ignores the value and returns true
653 return generator
.emitLoad(generator
.finalDestination(dst
), true);
656 // ------------------------------ VoidNode -------------------------------------
658 RegisterID
* VoidNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
660 if (dst
== generator
.ignoredResult()) {
661 generator
.emitNode(generator
.ignoredResult(), m_expr
);
664 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
665 return generator
.emitLoad(dst
, jsUndefined());
668 // ------------------------------ TypeOfValueNode -----------------------------------
670 RegisterID
* TypeOfResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
672 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
673 if (dst
== generator
.ignoredResult())
675 return generator
.emitTypeOf(generator
.finalDestination(dst
), local
);
678 RefPtr
<RegisterID
> scratch
= generator
.emitResolveBase(generator
.tempDestination(dst
), m_ident
);
679 generator
.emitGetById(scratch
.get(), scratch
.get(), m_ident
);
680 if (dst
== generator
.ignoredResult())
682 return generator
.emitTypeOf(generator
.finalDestination(dst
, scratch
.get()), scratch
.get());
685 // ------------------------------ TypeOfValueNode -----------------------------------
687 RegisterID
* TypeOfValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
689 if (dst
== generator
.ignoredResult()) {
690 generator
.emitNode(generator
.ignoredResult(), m_expr
);
693 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
694 return generator
.emitTypeOf(generator
.finalDestination(dst
), src
.get());
697 // ------------------------------ PrefixResolveNode ----------------------------------
699 RegisterID
* PrefixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
701 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
702 if (generator
.isLocalConstant(m_ident
)) {
703 if (dst
== generator
.ignoredResult())
705 RefPtr
<RegisterID
> r0
= generator
.emitLoad(generator
.finalDestination(dst
), (m_operator
== OpPlusPlus
) ? 1.0 : -1.0);
706 return generator
.emitBinaryOp(op_add
, r0
.get(), local
, r0
.get(), OperandTypes());
709 emitPreIncOrDec(generator
, local
, m_operator
);
710 return generator
.moveToDestinationIfNeeded(dst
, local
);
715 JSObject
* globalObject
= 0;
716 bool requiresDynamicChecks
= false;
717 if (generator
.findScopedProperty(m_ident
, index
, depth
, false, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
718 RefPtr
<RegisterID
> propDst
= generator
.emitGetScopedVar(generator
.tempDestination(dst
), depth
, index
, globalObject
);
719 emitPreIncOrDec(generator
, propDst
.get(), m_operator
);
720 generator
.emitPutScopedVar(depth
, index
, propDst
.get(), globalObject
);
721 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
724 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
725 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
726 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), propDst
.get(), m_ident
);
727 emitPreIncOrDec(generator
, propDst
.get(), m_operator
);
728 generator
.emitPutById(base
.get(), m_ident
, propDst
.get());
729 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
732 // ------------------------------ PrefixBracketNode ----------------------------------
734 RegisterID
* PrefixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
736 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
737 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
738 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
740 generator
.emitExpressionInfo(divot() + m_subexpressionDivotOffset
, m_subexpressionStartOffset
, endOffset() - m_subexpressionDivotOffset
);
741 RegisterID
* value
= generator
.emitGetByVal(propDst
.get(), base
.get(), property
.get());
742 if (m_operator
== OpPlusPlus
)
743 generator
.emitPreInc(value
);
745 generator
.emitPreDec(value
);
746 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
747 generator
.emitPutByVal(base
.get(), property
.get(), value
);
748 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
751 // ------------------------------ PrefixDotNode ----------------------------------
753 RegisterID
* PrefixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
755 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
756 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
758 generator
.emitExpressionInfo(divot() + m_subexpressionDivotOffset
, m_subexpressionStartOffset
, endOffset() - m_subexpressionDivotOffset
);
759 RegisterID
* value
= generator
.emitGetById(propDst
.get(), base
.get(), m_ident
);
760 if (m_operator
== OpPlusPlus
)
761 generator
.emitPreInc(value
);
763 generator
.emitPreDec(value
);
764 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
765 generator
.emitPutById(base
.get(), m_ident
, value
);
766 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
769 // ------------------------------ PrefixErrorNode -----------------------------------
771 RegisterID
* PrefixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
773 return emitThrowError(generator
, ReferenceError
, m_operator
== OpPlusPlus
774 ? "Prefix ++ operator applied to value that is not a reference."
775 : "Prefix -- operator applied to value that is not a reference.");
778 // ------------------------------ Unary Operation Nodes -----------------------------------
780 RegisterID
* UnaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
782 RegisterID
* src
= generator
.emitNode(m_expr
);
783 return generator
.emitUnaryOp(opcodeID(), generator
.finalDestination(dst
), src
);
787 // ------------------------------ LogicalNotNode -----------------------------------
789 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
791 ASSERT(expr()->hasConditionContextCodegen());
793 // reverse the true and false targets
794 generator
.emitNodeInConditionContext(expr(), falseTarget
, trueTarget
, !fallThroughMeansTrue
);
798 // ------------------------------ Binary Operation Nodes -----------------------------------
800 // BinaryOpNode::emitStrcat:
802 // This node generates an op_strcat operation. This opcode can handle concatenation of three or
803 // more values, where we can determine a set of separate op_add operations would be operating on
806 // This function expects to be operating on a graph of AST nodes looking something like this:
816 // The assignment operation is optional, if it exists the register holding the value on the
817 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
819 // The method should be called on the node at the root of the tree of regular binary add
820 // operations (marked in the diagram with a double set of parentheses). This node must
821 // be performing a string concatenation (determined by statically detecting that at least
822 // one child must be a string).
824 // Since the minimum number of values being concatenated together is expected to be 3, if
825 // a lhs to a concatenating assignment is not provided then the root add should have at
826 // least one left child that is also an add that can be determined to be operating on strings.
828 RegisterID
* BinaryOpNode::emitStrcat(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* lhs
, ReadModifyResolveNode
* emitExpressionInfoForMe
)
831 ASSERT(resultDescriptor().definitelyIsString());
833 // Create a list of expressions for all the adds in the tree of nodes we can convert into
834 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
835 // added first, and the leftmost child is never added, so the vector produced for the
836 // example above will be [ c, b ].
837 Vector
<ExpressionNode
*, 16> reverseExpressionList
;
838 reverseExpressionList
.append(m_expr2
);
840 // Examine the left child of the add. So long as this is a string add, add its right-child
841 // to the list, and keep processing along the left fork.
842 ExpressionNode
* leftMostAddChild
= m_expr1
;
843 while (leftMostAddChild
->isAdd() && leftMostAddChild
->resultDescriptor().definitelyIsString()) {
844 reverseExpressionList
.append(static_cast<AddNode
*>(leftMostAddChild
)->m_expr2
);
845 leftMostAddChild
= static_cast<AddNode
*>(leftMostAddChild
)->m_expr1
;
848 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
850 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
851 // We could possibly avoid this (the lhs is converted last anyway, we could let the
852 // op_strcat node handle its conversion if required).
854 temporaryRegisters
.append(generator
.newTemporary());
856 // Emit code for the leftmost node ((a) in the example).
857 temporaryRegisters
.append(generator
.newTemporary());
858 RegisterID
* leftMostAddChildTempRegister
= temporaryRegisters
.last().get();
859 generator
.emitNode(leftMostAddChildTempRegister
, leftMostAddChild
);
861 // Note on ordering of conversions:
863 // We maintain the same ordering of conversions as we would see if the concatenations
864 // was performed as a sequence of adds (otherwise this optimization could change
865 // behaviour should an object have been provided a valueOf or toString method).
867 // Considering the above example, the sequnce of execution is:
868 // * evaluate operand (a)
869 // * evaluate operand (b)
870 // * convert (a) to primitive <- (this would be triggered by the first add)
871 // * convert (b) to primitive <- (ditto)
872 // * evaluate operand (c)
873 // * convert (c) to primitive <- (this would be triggered by the second add)
874 // And optionally, if there is an assignment:
875 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
877 // As such we do not plant an op to convert the leftmost child now. Instead, use
878 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
879 // once the second node has been generated. However, if the leftmost child is an
880 // immediate we can trivially determine that no conversion will be required.
881 // If this is the case
882 if (leftMostAddChild
->isString())
883 leftMostAddChildTempRegister
= 0;
885 while (reverseExpressionList
.size()) {
886 ExpressionNode
* node
= reverseExpressionList
.last();
887 reverseExpressionList
.removeLast();
889 // Emit the code for the current node.
890 temporaryRegisters
.append(generator
.newTemporary());
891 generator
.emitNode(temporaryRegisters
.last().get(), node
);
893 // On the first iteration of this loop, when we first reach this point we have just
894 // generated the second node, which means it is time to convert the leftmost operand.
895 if (leftMostAddChildTempRegister
) {
896 generator
.emitToPrimitive(leftMostAddChildTempRegister
, leftMostAddChildTempRegister
);
897 leftMostAddChildTempRegister
= 0; // Only do this once.
899 // Plant a conversion for this node, if necessary.
900 if (!node
->isString())
901 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
903 ASSERT(temporaryRegisters
.size() >= 3);
905 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
906 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
907 if (emitExpressionInfoForMe
)
908 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
910 // If there is an assignment convert the lhs now. This will also copy lhs to
911 // the temporary register we allocated for it.
913 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
915 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
918 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
920 OpcodeID opcodeID
= this->opcodeID();
922 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString())
923 return emitStrcat(generator
, dst
);
925 if (opcodeID
== op_neq
) {
926 if (m_expr1
->isNull() || m_expr2
->isNull()) {
927 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
928 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
929 return generator
.emitUnaryOp(op_neq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
933 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
934 RegisterID
* src2
= generator
.emitNode(m_expr2
);
935 return generator
.emitBinaryOp(opcodeID
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
938 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
940 if (m_expr1
->isNull() || m_expr2
->isNull()) {
941 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
942 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
943 return generator
.emitUnaryOp(op_eq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
946 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
947 RegisterID
* src2
= generator
.emitNode(m_expr2
);
948 return generator
.emitEqualityOp(op_eq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
951 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
953 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
954 RegisterID
* src2
= generator
.emitNode(m_expr2
);
955 return generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
958 RegisterID
* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
960 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
961 RegisterID
* src2
= generator
.emitNode(m_expr2
);
962 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src2
, src1
.get(), OperandTypes(m_expr2
->resultDescriptor(), m_expr1
->resultDescriptor()));
965 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
967 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
968 RegisterID
* src2
= generator
.emitNode(m_expr2
);
969 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
970 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
973 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
975 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
976 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
978 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
979 generator
.emitGetByIdExceptionInfo(op_instanceof
);
980 RegisterID
* src2Prototype
= generator
.emitGetById(generator
.newTemporary(), src2
.get(), generator
.globalData()->propertyNames
->prototype
);
982 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
983 return generator
.emitInstanceOf(generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), src2Prototype
);
986 // ------------------------------ LogicalOpNode ----------------------------
988 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
990 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
991 RefPtr
<Label
> target
= generator
.newLabel();
993 generator
.emitNode(temp
.get(), m_expr1
);
994 if (m_operator
== OpLogicalAnd
)
995 generator
.emitJumpIfFalse(temp
.get(), target
.get());
997 generator
.emitJumpIfTrue(temp
.get(), target
.get());
998 generator
.emitNode(temp
.get(), m_expr2
);
999 generator
.emitLabel(target
.get());
1001 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
1004 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
1006 if (m_expr1
->hasConditionContextCodegen()) {
1007 RefPtr
<Label
> afterExpr1
= generator
.newLabel();
1008 if (m_operator
== OpLogicalAnd
)
1009 generator
.emitNodeInConditionContext(m_expr1
, afterExpr1
.get(), falseTarget
, true);
1011 generator
.emitNodeInConditionContext(m_expr1
, trueTarget
, afterExpr1
.get(), false);
1012 generator
.emitLabel(afterExpr1
.get());
1014 RegisterID
* temp
= generator
.emitNode(m_expr1
);
1015 if (m_operator
== OpLogicalAnd
)
1016 generator
.emitJumpIfFalse(temp
, falseTarget
);
1018 generator
.emitJumpIfTrue(temp
, trueTarget
);
1021 if (m_expr2
->hasConditionContextCodegen())
1022 generator
.emitNodeInConditionContext(m_expr2
, trueTarget
, falseTarget
, fallThroughMeansTrue
);
1024 RegisterID
* temp
= generator
.emitNode(m_expr2
);
1025 if (fallThroughMeansTrue
)
1026 generator
.emitJumpIfFalse(temp
, falseTarget
);
1028 generator
.emitJumpIfTrue(temp
, trueTarget
);
1032 // ------------------------------ ConditionalNode ------------------------------
1034 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1036 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
1037 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1038 RefPtr
<Label
> afterElse
= generator
.newLabel();
1040 if (m_logical
->hasConditionContextCodegen()) {
1041 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1042 generator
.emitNodeInConditionContext(m_logical
, beforeThen
.get(), beforeElse
.get(), true);
1043 generator
.emitLabel(beforeThen
.get());
1045 RegisterID
* cond
= generator
.emitNode(m_logical
);
1046 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1049 generator
.emitNode(newDst
.get(), m_expr1
);
1050 generator
.emitJump(afterElse
.get());
1052 generator
.emitLabel(beforeElse
.get());
1053 generator
.emitNode(newDst
.get(), m_expr2
);
1055 generator
.emitLabel(afterElse
.get());
1057 return newDst
.get();
1060 // ------------------------------ ReadModifyResolveNode -----------------------------------
1062 // FIXME: should this be moved to be a method on BytecodeGenerator?
1063 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1074 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1075 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1082 opcodeID
= op_lshift
;
1085 opcodeID
= op_rshift
;
1088 opcodeID
= op_urshift
;
1091 opcodeID
= op_bitand
;
1094 opcodeID
= op_bitxor
;
1097 opcodeID
= op_bitor
;
1103 ASSERT_NOT_REACHED();
1107 RegisterID
* src2
= generator
.emitNode(m_right
);
1109 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1110 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1111 if (emitExpressionInfoForMe
)
1112 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
1114 return generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1117 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1119 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1120 if (generator
.isLocalConstant(m_ident
)) {
1121 return emitReadModifyAssignment(generator
, generator
.finalDestination(dst
), local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1124 if (generator
.leftHandSideNeedsCopy(m_rightHasAssignments
, m_right
->isPure(generator
))) {
1125 RefPtr
<RegisterID
> result
= generator
.newTemporary();
1126 generator
.emitMove(result
.get(), local
);
1127 emitReadModifyAssignment(generator
, result
.get(), result
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1128 generator
.emitMove(local
, result
.get());
1129 return generator
.moveToDestinationIfNeeded(dst
, result
.get());
1132 RegisterID
* result
= emitReadModifyAssignment(generator
, local
, local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1133 return generator
.moveToDestinationIfNeeded(dst
, result
);
1138 JSObject
* globalObject
= 0;
1139 bool requiresDynamicChecks
= false;
1140 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
1141 RefPtr
<RegisterID
> src1
= generator
.emitGetScopedVar(generator
.tempDestination(dst
), depth
, index
, globalObject
);
1142 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1143 generator
.emitPutScopedVar(depth
, index
, result
, globalObject
);
1147 RefPtr
<RegisterID
> src1
= generator
.tempDestination(dst
);
1148 generator
.emitExpressionInfo(divot() - startOffset() + m_ident
.size(), m_ident
.size(), 0);
1149 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), src1
.get(), m_ident
);
1150 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()), this);
1151 return generator
.emitPutById(base
.get(), m_ident
, result
);
1154 // ------------------------------ AssignResolveNode -----------------------------------
1156 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1158 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1159 if (generator
.isLocalConstant(m_ident
))
1160 return generator
.emitNode(dst
, m_right
);
1162 RegisterID
* result
= generator
.emitNode(local
, m_right
);
1163 return generator
.moveToDestinationIfNeeded(dst
, result
);
1168 JSObject
* globalObject
= 0;
1169 bool requiresDynamicChecks
= false;
1170 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
1171 if (dst
== generator
.ignoredResult())
1173 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1174 generator
.emitPutScopedVar(depth
, index
, value
, globalObject
);
1178 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1179 if (dst
== generator
.ignoredResult())
1181 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1182 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1183 return generator
.emitPutById(base
.get(), m_ident
, value
);
1186 // ------------------------------ AssignDotNode -----------------------------------
1188 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1190 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1191 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1192 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1193 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1194 generator
.emitPutById(base
.get(), m_ident
, result
);
1195 return generator
.moveToDestinationIfNeeded(dst
, result
);
1198 // ------------------------------ ReadModifyDotNode -----------------------------------
1200 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1202 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1204 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1205 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
1206 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1208 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1209 return generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1212 // ------------------------------ AssignErrorNode -----------------------------------
1214 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1216 return emitThrowError(generator
, ReferenceError
, "Left side of assignment is not a reference.");
1219 // ------------------------------ AssignBracketNode -----------------------------------
1221 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1223 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1224 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1225 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1226 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1228 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1229 generator
.emitPutByVal(base
.get(), property
.get(), result
);
1230 return generator
.moveToDestinationIfNeeded(dst
, result
);
1233 // ------------------------------ ReadModifyBracketNode -----------------------------------
1235 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1237 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1238 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1240 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1241 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
1242 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1244 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1245 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1247 return updatedValue
;
1250 // ------------------------------ CommaNode ------------------------------------
1252 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1254 ASSERT(m_expressions
.size() > 1);
1255 for (size_t i
= 0; i
< m_expressions
.size() - 1; i
++)
1256 generator
.emitNode(generator
.ignoredResult(), m_expressions
[i
]);
1257 return generator
.emitNode(dst
, m_expressions
.last());
1260 // ------------------------------ ConstDeclNode ------------------------------------
1262 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1264 if (RegisterID
* local
= generator
.constRegisterFor(m_ident
)) {
1268 return generator
.emitNode(local
, m_init
);
1271 if (generator
.codeType() != EvalCode
) {
1273 return generator
.emitNode(m_init
);
1275 return generator
.emitResolve(generator
.newTemporary(), m_ident
);
1277 // FIXME: While this code should only be hit in eval code, it will potentially
1278 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1279 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1280 RegisterID
* value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1281 return generator
.emitPutById(base
.get(), m_ident
, value
);
1284 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1286 RegisterID
* result
= 0;
1287 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1288 result
= n
->emitCodeSingle(generator
);
1293 // ------------------------------ ConstStatementNode -----------------------------
1295 RegisterID
* ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1297 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1298 return generator
.emitNode(m_next
);
1301 // ------------------------------ SourceElements -------------------------------
1304 inline StatementNode
* SourceElements::lastStatement() const
1306 size_t size
= m_statements
.size();
1307 return size
? m_statements
[size
- 1] : 0;
1310 inline void SourceElements::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1312 size_t size
= m_statements
.size();
1313 for (size_t i
= 0; i
< size
; ++i
)
1314 generator
.emitNode(dst
, m_statements
[i
]);
1317 // ------------------------------ BlockNode ------------------------------------
1319 inline StatementNode
* BlockNode::lastStatement() const
1321 return m_statements
? m_statements
->lastStatement() : 0;
1324 RegisterID
* BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1327 m_statements
->emitBytecode(generator
, dst
);
1331 // ------------------------------ EmptyStatementNode ---------------------------
1333 RegisterID
* EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1335 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1339 // ------------------------------ DebuggerStatementNode ---------------------------
1341 RegisterID
* DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1343 generator
.emitDebugHook(DidReachBreakpoint
, firstLine(), lastLine());
1347 // ------------------------------ ExprStatementNode ----------------------------
1349 RegisterID
* ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1352 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1353 return generator
.emitNode(dst
, m_expr
);
1356 // ------------------------------ VarStatementNode ----------------------------
1358 RegisterID
* VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1361 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1362 return generator
.emitNode(m_expr
);
1365 // ------------------------------ IfNode ---------------------------------------
1367 RegisterID
* IfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1369 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1371 RefPtr
<Label
> afterThen
= generator
.newLabel();
1373 if (m_condition
->hasConditionContextCodegen()) {
1374 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1375 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), afterThen
.get(), true);
1376 generator
.emitLabel(beforeThen
.get());
1378 RegisterID
* cond
= generator
.emitNode(m_condition
);
1379 generator
.emitJumpIfFalse(cond
, afterThen
.get());
1382 generator
.emitNode(dst
, m_ifBlock
);
1383 generator
.emitLabel(afterThen
.get());
1385 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1389 // ------------------------------ IfElseNode ---------------------------------------
1391 RegisterID
* IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1393 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1395 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1396 RefPtr
<Label
> afterElse
= generator
.newLabel();
1398 if (m_condition
->hasConditionContextCodegen()) {
1399 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1400 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), beforeElse
.get(), true);
1401 generator
.emitLabel(beforeThen
.get());
1403 RegisterID
* cond
= generator
.emitNode(m_condition
);
1404 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1407 generator
.emitNode(dst
, m_ifBlock
);
1408 generator
.emitJump(afterElse
.get());
1410 generator
.emitLabel(beforeElse
.get());
1412 generator
.emitNode(dst
, m_elseBlock
);
1414 generator
.emitLabel(afterElse
.get());
1416 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1420 // ------------------------------ DoWhileNode ----------------------------------
1422 RegisterID
* DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1424 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1426 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1427 generator
.emitLabel(topOfLoop
.get());
1429 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1431 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1433 generator
.emitLabel(scope
->continueTarget());
1434 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1435 if (m_expr
->hasConditionContextCodegen())
1436 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1438 RegisterID
* cond
= generator
.emitNode(m_expr
);
1439 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1442 generator
.emitLabel(scope
->breakTarget());
1443 return result
.get();
1446 // ------------------------------ WhileNode ------------------------------------
1448 RegisterID
* WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1450 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1452 generator
.emitJump(scope
->continueTarget());
1454 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1455 generator
.emitLabel(topOfLoop
.get());
1457 generator
.emitNode(dst
, m_statement
);
1459 generator
.emitLabel(scope
->continueTarget());
1460 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1462 if (m_expr
->hasConditionContextCodegen())
1463 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1465 RegisterID
* cond
= generator
.emitNode(m_expr
);
1466 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1469 generator
.emitLabel(scope
->breakTarget());
1471 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1475 // ------------------------------ ForNode --------------------------------------
1477 RegisterID
* ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1479 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1481 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1484 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
1486 RefPtr
<Label
> condition
= generator
.newLabel();
1487 generator
.emitJump(condition
.get());
1489 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1490 generator
.emitLabel(topOfLoop
.get());
1492 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1494 generator
.emitLabel(scope
->continueTarget());
1495 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1497 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
1499 generator
.emitLabel(condition
.get());
1501 if (m_expr2
->hasConditionContextCodegen())
1502 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), false);
1504 RegisterID
* cond
= generator
.emitNode(m_expr2
);
1505 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1508 generator
.emitJump(topOfLoop
.get());
1510 generator
.emitLabel(scope
->breakTarget());
1511 return result
.get();
1514 // ------------------------------ ForInNode ------------------------------------
1516 RegisterID
* ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1518 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1520 if (!m_lexpr
->isLocation())
1521 return emitThrowError(generator
, ReferenceError
, "Left side of for-in statement is not a reference.");
1523 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1526 generator
.emitNode(generator
.ignoredResult(), m_init
);
1528 RefPtr
<RegisterID
> base
= generator
.newTemporary();
1529 generator
.emitNode(base
.get(), m_expr
);
1530 RefPtr
<RegisterID
> i
= generator
.newTemporary();
1531 RefPtr
<RegisterID
> size
= generator
.newTemporary();
1532 RefPtr
<RegisterID
> expectedSubscript
;
1533 RefPtr
<RegisterID
> iter
= generator
.emitGetPropertyNames(generator
.newTemporary(), base
.get(), i
.get(), size
.get(), scope
->breakTarget());
1534 generator
.emitJump(scope
->continueTarget());
1536 RefPtr
<Label
> loopStart
= generator
.newLabel();
1537 generator
.emitLabel(loopStart
.get());
1539 RegisterID
* propertyName
;
1540 bool optimizedForinAccess
= false;
1541 if (m_lexpr
->isResolveNode()) {
1542 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1543 propertyName
= generator
.registerFor(ident
);
1544 if (!propertyName
) {
1545 propertyName
= generator
.newTemporary();
1546 RefPtr
<RegisterID
> protect
= propertyName
;
1547 RegisterID
* base
= generator
.emitResolveBase(generator
.newTemporary(), ident
);
1549 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1550 generator
.emitPutById(base
, ident
, propertyName
);
1552 expectedSubscript
= generator
.emitMove(generator
.newTemporary(), propertyName
);
1553 generator
.pushOptimisedForIn(expectedSubscript
.get(), iter
.get(), i
.get(), propertyName
);
1554 optimizedForinAccess
= true;
1556 } else if (m_lexpr
->isDotAccessorNode()) {
1557 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1558 const Identifier
& ident
= assignNode
->identifier();
1559 propertyName
= generator
.newTemporary();
1560 RefPtr
<RegisterID
> protect
= propertyName
;
1561 RegisterID
* base
= generator
.emitNode(assignNode
->base());
1563 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1564 generator
.emitPutById(base
, ident
, propertyName
);
1566 ASSERT(m_lexpr
->isBracketAccessorNode());
1567 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1568 propertyName
= generator
.newTemporary();
1569 RefPtr
<RegisterID
> protect
= propertyName
;
1570 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1571 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1573 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1574 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
1577 generator
.emitNode(dst
, m_statement
);
1579 if (optimizedForinAccess
)
1580 generator
.popOptimisedForIn();
1582 generator
.emitLabel(scope
->continueTarget());
1583 generator
.emitNextPropertyName(propertyName
, base
.get(), i
.get(), size
.get(), iter
.get(), loopStart
.get());
1584 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1585 generator
.emitLabel(scope
->breakTarget());
1589 // ------------------------------ ContinueNode ---------------------------------
1592 RegisterID
* ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1594 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1596 LabelScope
* scope
= generator
.continueTarget(m_ident
);
1599 return m_ident
.isEmpty()
1600 ? emitThrowError(generator
, SyntaxError
, "Invalid continue statement.")
1601 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1603 generator
.emitJumpScopes(scope
->continueTarget(), scope
->scopeDepth());
1607 // ------------------------------ BreakNode ------------------------------------
1610 RegisterID
* BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1612 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1614 LabelScope
* scope
= generator
.breakTarget(m_ident
);
1617 return m_ident
.isEmpty()
1618 ? emitThrowError(generator
, SyntaxError
, "Invalid break statement.")
1619 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1621 generator
.emitJumpScopes(scope
->breakTarget(), scope
->scopeDepth());
1625 // ------------------------------ ReturnNode -----------------------------------
1627 RegisterID
* ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1629 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1630 if (generator
.codeType() != FunctionCode
)
1631 return emitThrowError(generator
, SyntaxError
, "Invalid return statement.");
1633 if (dst
== generator
.ignoredResult())
1635 RegisterID
* r0
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
1636 RefPtr
<RegisterID
> returnRegister
;
1637 if (generator
.scopeDepth()) {
1638 RefPtr
<Label
> l0
= generator
.newLabel();
1639 if (generator
.hasFinaliser() && !r0
->isTemporary()) {
1640 returnRegister
= generator
.emitMove(generator
.newTemporary(), r0
);
1641 r0
= returnRegister
.get();
1643 generator
.emitJumpScopes(l0
.get(), 0);
1644 generator
.emitLabel(l0
.get());
1646 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1647 return generator
.emitReturn(r0
);
1650 // ------------------------------ WithNode -------------------------------------
1652 RegisterID
* WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1654 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1656 RefPtr
<RegisterID
> scope
= generator
.newTemporary();
1657 generator
.emitNode(scope
.get(), m_expr
); // scope must be protected until popped
1658 generator
.emitExpressionInfo(m_divot
, m_expressionLength
, 0);
1659 generator
.emitPushScope(scope
.get());
1660 RegisterID
* result
= generator
.emitNode(dst
, m_statement
);
1661 generator
.emitPopScope();
1665 // ------------------------------ CaseClauseNode --------------------------------
1667 inline void CaseClauseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1670 m_statements
->emitBytecode(generator
, dst
);
1673 // ------------------------------ CaseBlockNode --------------------------------
1682 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
1684 for (; list
; list
= list
->getNext()) {
1685 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
1686 literalVector
.append(clauseExpression
);
1687 if (clauseExpression
->isNumber()) {
1688 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
1689 int32_t intVal
= static_cast<int32_t>(value
);
1690 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
1691 typeForTable
= SwitchNeither
;
1694 if (intVal
< min_num
)
1696 if (intVal
> max_num
)
1698 typeForTable
= SwitchNumber
;
1701 if (clauseExpression
->isString()) {
1702 if (typeForTable
& ~SwitchString
) {
1703 typeForTable
= SwitchNeither
;
1706 const UString
& value
= static_cast<StringNode
*>(clauseExpression
)->value().ustring();
1707 if (singleCharacterSwitch
&= value
.size() == 1) {
1708 int32_t intVal
= value
.rep()->characters()[0];
1709 if (intVal
< min_num
)
1711 if (intVal
> max_num
)
1714 typeForTable
= SwitchString
;
1717 typeForTable
= SwitchNeither
;
1722 SwitchInfo::SwitchType
CaseBlockNode::tryOptimizedSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
1724 SwitchKind typeForTable
= SwitchUnset
;
1725 bool singleCharacterSwitch
= true;
1727 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1728 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1730 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
1731 return SwitchInfo::SwitchNone
;
1733 if (typeForTable
== SwitchNumber
) {
1734 int32_t range
= max_num
- min_num
;
1735 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1736 return SwitchInfo::SwitchImmediate
;
1737 return SwitchInfo::SwitchNone
;
1740 ASSERT(typeForTable
== SwitchString
);
1742 if (singleCharacterSwitch
) {
1743 int32_t range
= max_num
- min_num
;
1744 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1745 return SwitchInfo::SwitchCharacter
;
1748 return SwitchInfo::SwitchString
;
1751 RegisterID
* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
1753 RefPtr
<Label
> defaultLabel
;
1754 Vector
<RefPtr
<Label
>, 8> labelVector
;
1755 Vector
<ExpressionNode
*, 8> literalVector
;
1756 int32_t min_num
= std::numeric_limits
<int32_t>::max();
1757 int32_t max_num
= std::numeric_limits
<int32_t>::min();
1758 SwitchInfo::SwitchType switchType
= tryOptimizedSwitch(literalVector
, min_num
, max_num
);
1760 if (switchType
!= SwitchInfo::SwitchNone
) {
1761 // Prepare the various labels
1762 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
1763 labelVector
.append(generator
.newLabel());
1764 defaultLabel
= generator
.newLabel();
1765 generator
.beginSwitch(switchExpression
, switchType
);
1768 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1769 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1770 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1771 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1772 labelVector
.append(generator
.newLabel());
1773 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1776 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1777 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1778 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1779 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1780 labelVector
.append(generator
.newLabel());
1781 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1783 defaultLabel
= generator
.newLabel();
1784 generator
.emitJump(defaultLabel
.get());
1787 RegisterID
* result
= 0;
1790 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1791 generator
.emitLabel(labelVector
[i
++].get());
1792 list
->getClause()->emitBytecode(generator
, dst
);
1795 if (m_defaultClause
) {
1796 generator
.emitLabel(defaultLabel
.get());
1797 m_defaultClause
->emitBytecode(generator
, dst
);
1800 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1801 generator
.emitLabel(labelVector
[i
++].get());
1802 list
->getClause()->emitBytecode(generator
, dst
);
1804 if (!m_defaultClause
)
1805 generator
.emitLabel(defaultLabel
.get());
1807 ASSERT(i
== labelVector
.size());
1808 if (switchType
!= SwitchInfo::SwitchNone
) {
1809 ASSERT(labelVector
.size() == literalVector
.size());
1810 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
1815 // ------------------------------ SwitchNode -----------------------------------
1817 RegisterID
* SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1819 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1821 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Switch
);
1823 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
1824 RegisterID
* r1
= m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
1826 generator
.emitLabel(scope
->breakTarget());
1830 // ------------------------------ LabelNode ------------------------------------
1832 RegisterID
* LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1834 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1836 if (generator
.breakTarget(m_name
))
1837 return emitThrowError(generator
, SyntaxError
, "Duplicate label: %s.", m_name
);
1839 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
1840 RegisterID
* r0
= generator
.emitNode(dst
, m_statement
);
1842 generator
.emitLabel(scope
->breakTarget());
1846 // ------------------------------ ThrowNode ------------------------------------
1848 RegisterID
* ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1850 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1852 if (dst
== generator
.ignoredResult())
1854 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
1855 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1856 generator
.emitThrow(expr
.get());
1860 // ------------------------------ TryNode --------------------------------------
1862 RegisterID
* TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1864 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1865 // optimizer knows they may be jumped to from anywhere.
1867 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1869 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
1870 RefPtr
<Label
> finallyStart
;
1871 RefPtr
<RegisterID
> finallyReturnAddr
;
1872 if (m_finallyBlock
) {
1873 finallyStart
= generator
.newLabel();
1874 finallyReturnAddr
= generator
.newTemporary();
1875 generator
.pushFinallyContext(finallyStart
.get(), finallyReturnAddr
.get());
1878 generator
.emitLabel(tryStartLabel
.get());
1879 generator
.emitNode(dst
, m_tryBlock
);
1882 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
1884 // Normal path: jump over the catch block.
1885 generator
.emitJump(catchEndLabel
.get());
1887 // Uncaught exception path: the catch block.
1888 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1889 RefPtr
<RegisterID
> exceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1890 if (m_catchHasEval
) {
1891 RefPtr
<RegisterID
> dynamicScopeObject
= generator
.emitNewObject(generator
.newTemporary());
1892 generator
.emitPutById(dynamicScopeObject
.get(), m_exceptionIdent
, exceptionRegister
.get());
1893 generator
.emitMove(exceptionRegister
.get(), dynamicScopeObject
.get());
1894 generator
.emitPushScope(exceptionRegister
.get());
1896 generator
.emitPushNewScope(exceptionRegister
.get(), m_exceptionIdent
, exceptionRegister
.get());
1897 generator
.emitNode(dst
, m_catchBlock
);
1898 generator
.emitPopScope();
1899 generator
.emitLabel(catchEndLabel
.get());
1902 if (m_finallyBlock
) {
1903 generator
.popFinallyContext();
1904 // there may be important registers live at the time we jump
1905 // to a finally block (such as for a return or throw) so we
1906 // ref the highest register ever used as a conservative
1907 // approach to not clobbering anything important
1908 RefPtr
<RegisterID
> highestUsedRegister
= generator
.highestUsedRegister();
1909 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
1911 // Normal path: invoke the finally block, then jump over it.
1912 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1913 generator
.emitJump(finallyEndLabel
.get());
1915 // Uncaught exception path: invoke the finally block, then re-throw the exception.
1916 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1917 RefPtr
<RegisterID
> tempExceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1918 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1919 generator
.emitThrow(tempExceptionRegister
.get());
1921 // The finally block.
1922 generator
.emitLabel(finallyStart
.get());
1923 generator
.emitNode(dst
, m_finallyBlock
);
1924 generator
.emitSubroutineReturn(finallyReturnAddr
.get());
1926 generator
.emitLabel(finallyEndLabel
.get());
1932 // ------------------------------ ScopeNode -----------------------------
1934 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1936 if (m_data
->m_statements
)
1937 m_data
->m_statements
->emitBytecode(generator
, dst
);
1940 // ------------------------------ ProgramNode -----------------------------
1942 RegisterID
* ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1944 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1946 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1947 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1948 emitStatementsBytecode(generator
, dstRegister
.get());
1950 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1951 generator
.emitEnd(dstRegister
.get());
1955 // ------------------------------ EvalNode -----------------------------
1957 RegisterID
* EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1959 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1961 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1962 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1963 emitStatementsBytecode(generator
, dstRegister
.get());
1965 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1966 generator
.emitEnd(dstRegister
.get());
1970 // ------------------------------ FunctionBodyNode -----------------------------
1972 RegisterID
* FunctionBodyNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1974 generator
.emitDebugHook(DidEnterCallFrame
, firstLine(), lastLine());
1975 emitStatementsBytecode(generator
, generator
.ignoredResult());
1976 StatementNode
* singleStatement
= this->singleStatement();
1977 if (singleStatement
&& singleStatement
->isBlock()) {
1978 StatementNode
* lastStatementInBlock
= static_cast<BlockNode
*>(singleStatement
)->lastStatement();
1979 if (lastStatementInBlock
&& lastStatementInBlock
->isReturnNode())
1983 RegisterID
* r0
= generator
.emitLoad(0, jsUndefined());
1984 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1985 generator
.emitReturn(r0
);
1989 // ------------------------------ FuncDeclNode ---------------------------------
1991 RegisterID
* FuncDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1993 if (dst
== generator
.ignoredResult())
1998 // ------------------------------ FuncExprNode ---------------------------------
2000 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2002 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);