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 IncreaseEmitNodeDepth
stackGuard(generator
, 3);
835 // Create a list of expressions for all the adds in the tree of nodes we can convert into
836 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
837 // added first, and the leftmost child is never added, so the vector produced for the
838 // example above will be [ c, b ].
839 Vector
<ExpressionNode
*, 16> reverseExpressionList
;
840 reverseExpressionList
.append(m_expr2
);
842 // Examine the left child of the add. So long as this is a string add, add its right-child
843 // to the list, and keep processing along the left fork.
844 ExpressionNode
* leftMostAddChild
= m_expr1
;
845 while (leftMostAddChild
->isAdd() && leftMostAddChild
->resultDescriptor().definitelyIsString()) {
846 reverseExpressionList
.append(static_cast<AddNode
*>(leftMostAddChild
)->m_expr2
);
847 leftMostAddChild
= static_cast<AddNode
*>(leftMostAddChild
)->m_expr1
;
850 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
852 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
853 // We could possibly avoid this (the lhs is converted last anyway, we could let the
854 // op_strcat node handle its conversion if required).
856 temporaryRegisters
.append(generator
.newTemporary());
858 // Emit code for the leftmost node ((a) in the example).
859 temporaryRegisters
.append(generator
.newTemporary());
860 RegisterID
* leftMostAddChildTempRegister
= temporaryRegisters
.last().get();
861 generator
.emitNode(leftMostAddChildTempRegister
, leftMostAddChild
);
863 // Note on ordering of conversions:
865 // We maintain the same ordering of conversions as we would see if the concatenations
866 // was performed as a sequence of adds (otherwise this optimization could change
867 // behaviour should an object have been provided a valueOf or toString method).
869 // Considering the above example, the sequnce of execution is:
870 // * evaluate operand (a)
871 // * evaluate operand (b)
872 // * convert (a) to primitive <- (this would be triggered by the first add)
873 // * convert (b) to primitive <- (ditto)
874 // * evaluate operand (c)
875 // * convert (c) to primitive <- (this would be triggered by the second add)
876 // And optionally, if there is an assignment:
877 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
879 // As such we do not plant an op to convert the leftmost child now. Instead, use
880 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
881 // once the second node has been generated. However, if the leftmost child is an
882 // immediate we can trivially determine that no conversion will be required.
883 // If this is the case
884 if (leftMostAddChild
->isString())
885 leftMostAddChildTempRegister
= 0;
887 while (reverseExpressionList
.size()) {
888 ExpressionNode
* node
= reverseExpressionList
.last();
889 reverseExpressionList
.removeLast();
891 // Emit the code for the current node.
892 temporaryRegisters
.append(generator
.newTemporary());
893 generator
.emitNode(temporaryRegisters
.last().get(), node
);
895 // On the first iteration of this loop, when we first reach this point we have just
896 // generated the second node, which means it is time to convert the leftmost operand.
897 if (leftMostAddChildTempRegister
) {
898 generator
.emitToPrimitive(leftMostAddChildTempRegister
, leftMostAddChildTempRegister
);
899 leftMostAddChildTempRegister
= 0; // Only do this once.
901 // Plant a conversion for this node, if necessary.
902 if (!node
->isString())
903 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
905 ASSERT(temporaryRegisters
.size() >= 3);
907 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
908 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
909 if (emitExpressionInfoForMe
)
910 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
912 // If there is an assignment convert the lhs now. This will also copy lhs to
913 // the temporary register we allocated for it.
915 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
917 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
920 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
922 OpcodeID opcodeID
= this->opcodeID();
924 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString())
925 return emitStrcat(generator
, dst
);
927 if (opcodeID
== op_neq
) {
928 if (m_expr1
->isNull() || m_expr2
->isNull()) {
929 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
930 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
931 return generator
.emitUnaryOp(op_neq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
935 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
936 RegisterID
* src2
= generator
.emitNode(m_expr2
);
937 return generator
.emitBinaryOp(opcodeID
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
940 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
942 if (m_expr1
->isNull() || m_expr2
->isNull()) {
943 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
944 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
945 return generator
.emitUnaryOp(op_eq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
948 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
949 RegisterID
* src2
= generator
.emitNode(m_expr2
);
950 return generator
.emitEqualityOp(op_eq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
953 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
955 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
956 RegisterID
* src2
= generator
.emitNode(m_expr2
);
957 return generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
960 RegisterID
* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
962 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
963 RegisterID
* src2
= generator
.emitNode(m_expr2
);
964 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src2
, src1
.get(), OperandTypes(m_expr2
->resultDescriptor(), m_expr1
->resultDescriptor()));
967 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
969 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
970 RegisterID
* src2
= generator
.emitNode(m_expr2
);
971 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
972 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
975 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
977 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
978 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
980 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
981 generator
.emitGetByIdExceptionInfo(op_instanceof
);
982 RegisterID
* src2Prototype
= generator
.emitGetById(generator
.newTemporary(), src2
.get(), generator
.globalData()->propertyNames
->prototype
);
984 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
985 return generator
.emitInstanceOf(generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), src2Prototype
);
988 // ------------------------------ LogicalOpNode ----------------------------
990 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
992 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
993 RefPtr
<Label
> target
= generator
.newLabel();
995 generator
.emitNode(temp
.get(), m_expr1
);
996 if (m_operator
== OpLogicalAnd
)
997 generator
.emitJumpIfFalse(temp
.get(), target
.get());
999 generator
.emitJumpIfTrue(temp
.get(), target
.get());
1000 generator
.emitNode(temp
.get(), m_expr2
);
1001 generator
.emitLabel(target
.get());
1003 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
1006 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
1008 if (m_expr1
->hasConditionContextCodegen()) {
1009 RefPtr
<Label
> afterExpr1
= generator
.newLabel();
1010 if (m_operator
== OpLogicalAnd
)
1011 generator
.emitNodeInConditionContext(m_expr1
, afterExpr1
.get(), falseTarget
, true);
1013 generator
.emitNodeInConditionContext(m_expr1
, trueTarget
, afterExpr1
.get(), false);
1014 generator
.emitLabel(afterExpr1
.get());
1016 RegisterID
* temp
= generator
.emitNode(m_expr1
);
1017 if (m_operator
== OpLogicalAnd
)
1018 generator
.emitJumpIfFalse(temp
, falseTarget
);
1020 generator
.emitJumpIfTrue(temp
, trueTarget
);
1023 if (m_expr2
->hasConditionContextCodegen())
1024 generator
.emitNodeInConditionContext(m_expr2
, trueTarget
, falseTarget
, fallThroughMeansTrue
);
1026 RegisterID
* temp
= generator
.emitNode(m_expr2
);
1027 if (fallThroughMeansTrue
)
1028 generator
.emitJumpIfFalse(temp
, falseTarget
);
1030 generator
.emitJumpIfTrue(temp
, trueTarget
);
1034 // ------------------------------ ConditionalNode ------------------------------
1036 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1038 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
1039 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1040 RefPtr
<Label
> afterElse
= generator
.newLabel();
1042 if (m_logical
->hasConditionContextCodegen()) {
1043 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1044 generator
.emitNodeInConditionContext(m_logical
, beforeThen
.get(), beforeElse
.get(), true);
1045 generator
.emitLabel(beforeThen
.get());
1047 RegisterID
* cond
= generator
.emitNode(m_logical
);
1048 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1051 generator
.emitNode(newDst
.get(), m_expr1
);
1052 generator
.emitJump(afterElse
.get());
1054 generator
.emitLabel(beforeElse
.get());
1055 generator
.emitNode(newDst
.get(), m_expr2
);
1057 generator
.emitLabel(afterElse
.get());
1059 return newDst
.get();
1062 // ------------------------------ ReadModifyResolveNode -----------------------------------
1064 // FIXME: should this be moved to be a method on BytecodeGenerator?
1065 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1076 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1077 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1084 opcodeID
= op_lshift
;
1087 opcodeID
= op_rshift
;
1090 opcodeID
= op_urshift
;
1093 opcodeID
= op_bitand
;
1096 opcodeID
= op_bitxor
;
1099 opcodeID
= op_bitor
;
1105 ASSERT_NOT_REACHED();
1109 RegisterID
* src2
= generator
.emitNode(m_right
);
1111 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1112 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1113 if (emitExpressionInfoForMe
)
1114 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
1116 return generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1119 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1121 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1122 if (generator
.isLocalConstant(m_ident
)) {
1123 return emitReadModifyAssignment(generator
, generator
.finalDestination(dst
), local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1126 if (generator
.leftHandSideNeedsCopy(m_rightHasAssignments
, m_right
->isPure(generator
))) {
1127 RefPtr
<RegisterID
> result
= generator
.newTemporary();
1128 generator
.emitMove(result
.get(), local
);
1129 emitReadModifyAssignment(generator
, result
.get(), result
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1130 generator
.emitMove(local
, result
.get());
1131 return generator
.moveToDestinationIfNeeded(dst
, result
.get());
1134 RegisterID
* result
= emitReadModifyAssignment(generator
, local
, local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1135 return generator
.moveToDestinationIfNeeded(dst
, result
);
1140 JSObject
* globalObject
= 0;
1141 bool requiresDynamicChecks
= false;
1142 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
1143 RefPtr
<RegisterID
> src1
= generator
.emitGetScopedVar(generator
.tempDestination(dst
), depth
, index
, globalObject
);
1144 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1145 generator
.emitPutScopedVar(depth
, index
, result
, globalObject
);
1149 RefPtr
<RegisterID
> src1
= generator
.tempDestination(dst
);
1150 generator
.emitExpressionInfo(divot() - startOffset() + m_ident
.size(), m_ident
.size(), 0);
1151 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), src1
.get(), m_ident
);
1152 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()), this);
1153 return generator
.emitPutById(base
.get(), m_ident
, result
);
1156 // ------------------------------ AssignResolveNode -----------------------------------
1158 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1160 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1161 if (generator
.isLocalConstant(m_ident
))
1162 return generator
.emitNode(dst
, m_right
);
1164 RegisterID
* result
= generator
.emitNode(local
, m_right
);
1165 return generator
.moveToDestinationIfNeeded(dst
, result
);
1170 JSObject
* globalObject
= 0;
1171 bool requiresDynamicChecks
= false;
1172 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
1173 if (dst
== generator
.ignoredResult())
1175 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1176 generator
.emitPutScopedVar(depth
, index
, value
, globalObject
);
1180 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1181 if (dst
== generator
.ignoredResult())
1183 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1184 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1185 return generator
.emitPutById(base
.get(), m_ident
, value
);
1188 // ------------------------------ AssignDotNode -----------------------------------
1190 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1192 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1193 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1194 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1195 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1196 generator
.emitPutById(base
.get(), m_ident
, result
);
1197 return generator
.moveToDestinationIfNeeded(dst
, result
);
1200 // ------------------------------ ReadModifyDotNode -----------------------------------
1202 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1204 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1206 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1207 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
1208 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1210 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1211 return generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1214 // ------------------------------ AssignErrorNode -----------------------------------
1216 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1218 return emitThrowError(generator
, ReferenceError
, "Left side of assignment is not a reference.");
1221 // ------------------------------ AssignBracketNode -----------------------------------
1223 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1225 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1226 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1227 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1228 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1230 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1231 generator
.emitPutByVal(base
.get(), property
.get(), result
);
1232 return generator
.moveToDestinationIfNeeded(dst
, result
);
1235 // ------------------------------ ReadModifyBracketNode -----------------------------------
1237 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1239 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1240 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1242 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1243 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
1244 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1246 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1247 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1249 return updatedValue
;
1252 // ------------------------------ CommaNode ------------------------------------
1254 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1256 ASSERT(m_expressions
.size() > 1);
1257 for (size_t i
= 0; i
< m_expressions
.size() - 1; i
++)
1258 generator
.emitNode(generator
.ignoredResult(), m_expressions
[i
]);
1259 return generator
.emitNode(dst
, m_expressions
.last());
1262 // ------------------------------ ConstDeclNode ------------------------------------
1264 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1266 if (RegisterID
* local
= generator
.constRegisterFor(m_ident
)) {
1270 return generator
.emitNode(local
, m_init
);
1273 if (generator
.codeType() != EvalCode
) {
1275 return generator
.emitNode(m_init
);
1277 return generator
.emitResolve(generator
.newTemporary(), m_ident
);
1279 // FIXME: While this code should only be hit in eval code, it will potentially
1280 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1281 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1282 RegisterID
* value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1283 return generator
.emitPutById(base
.get(), m_ident
, value
);
1286 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1288 RegisterID
* result
= 0;
1289 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1290 result
= n
->emitCodeSingle(generator
);
1295 // ------------------------------ ConstStatementNode -----------------------------
1297 RegisterID
* ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1299 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1300 return generator
.emitNode(m_next
);
1303 // ------------------------------ SourceElements -------------------------------
1306 inline StatementNode
* SourceElements::lastStatement() const
1308 size_t size
= m_statements
.size();
1309 return size
? m_statements
[size
- 1] : 0;
1312 inline void SourceElements::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1314 size_t size
= m_statements
.size();
1315 for (size_t i
= 0; i
< size
; ++i
)
1316 generator
.emitNode(dst
, m_statements
[i
]);
1319 // ------------------------------ BlockNode ------------------------------------
1321 inline StatementNode
* BlockNode::lastStatement() const
1323 return m_statements
? m_statements
->lastStatement() : 0;
1326 RegisterID
* BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1329 m_statements
->emitBytecode(generator
, dst
);
1333 // ------------------------------ EmptyStatementNode ---------------------------
1335 RegisterID
* EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1337 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1341 // ------------------------------ DebuggerStatementNode ---------------------------
1343 RegisterID
* DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1345 generator
.emitDebugHook(DidReachBreakpoint
, firstLine(), lastLine());
1349 // ------------------------------ ExprStatementNode ----------------------------
1351 RegisterID
* ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1354 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1355 return generator
.emitNode(dst
, m_expr
);
1358 // ------------------------------ VarStatementNode ----------------------------
1360 RegisterID
* VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1363 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1364 return generator
.emitNode(m_expr
);
1367 // ------------------------------ IfNode ---------------------------------------
1369 RegisterID
* IfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1371 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1373 RefPtr
<Label
> afterThen
= generator
.newLabel();
1375 if (m_condition
->hasConditionContextCodegen()) {
1376 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1377 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), afterThen
.get(), true);
1378 generator
.emitLabel(beforeThen
.get());
1380 RegisterID
* cond
= generator
.emitNode(m_condition
);
1381 generator
.emitJumpIfFalse(cond
, afterThen
.get());
1384 generator
.emitNode(dst
, m_ifBlock
);
1385 generator
.emitLabel(afterThen
.get());
1387 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1391 // ------------------------------ IfElseNode ---------------------------------------
1393 RegisterID
* IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1395 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1397 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1398 RefPtr
<Label
> afterElse
= generator
.newLabel();
1400 if (m_condition
->hasConditionContextCodegen()) {
1401 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1402 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), beforeElse
.get(), true);
1403 generator
.emitLabel(beforeThen
.get());
1405 RegisterID
* cond
= generator
.emitNode(m_condition
);
1406 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1409 generator
.emitNode(dst
, m_ifBlock
);
1410 generator
.emitJump(afterElse
.get());
1412 generator
.emitLabel(beforeElse
.get());
1414 generator
.emitNode(dst
, m_elseBlock
);
1416 generator
.emitLabel(afterElse
.get());
1418 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1422 // ------------------------------ DoWhileNode ----------------------------------
1424 RegisterID
* DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1426 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1428 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1429 generator
.emitLabel(topOfLoop
.get());
1431 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1433 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1435 generator
.emitLabel(scope
->continueTarget());
1436 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1437 if (m_expr
->hasConditionContextCodegen())
1438 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1440 RegisterID
* cond
= generator
.emitNode(m_expr
);
1441 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1444 generator
.emitLabel(scope
->breakTarget());
1445 return result
.get();
1448 // ------------------------------ WhileNode ------------------------------------
1450 RegisterID
* WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1452 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1454 generator
.emitJump(scope
->continueTarget());
1456 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1457 generator
.emitLabel(topOfLoop
.get());
1459 generator
.emitNode(dst
, m_statement
);
1461 generator
.emitLabel(scope
->continueTarget());
1462 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1464 if (m_expr
->hasConditionContextCodegen())
1465 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1467 RegisterID
* cond
= generator
.emitNode(m_expr
);
1468 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1471 generator
.emitLabel(scope
->breakTarget());
1473 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1477 // ------------------------------ ForNode --------------------------------------
1479 RegisterID
* ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1481 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1483 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1486 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
1488 RefPtr
<Label
> condition
= generator
.newLabel();
1489 generator
.emitJump(condition
.get());
1491 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1492 generator
.emitLabel(topOfLoop
.get());
1494 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1496 generator
.emitLabel(scope
->continueTarget());
1497 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1499 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
1501 generator
.emitLabel(condition
.get());
1503 if (m_expr2
->hasConditionContextCodegen())
1504 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), false);
1506 RegisterID
* cond
= generator
.emitNode(m_expr2
);
1507 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1510 generator
.emitJump(topOfLoop
.get());
1512 generator
.emitLabel(scope
->breakTarget());
1513 return result
.get();
1516 // ------------------------------ ForInNode ------------------------------------
1518 RegisterID
* ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1520 IncreaseEmitNodeDepth
stackGuard(generator
);
1522 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1524 if (!m_lexpr
->isLocation())
1525 return emitThrowError(generator
, ReferenceError
, "Left side of for-in statement is not a reference.");
1527 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1530 generator
.emitNode(generator
.ignoredResult(), m_init
);
1532 RefPtr
<RegisterID
> base
= generator
.newTemporary();
1533 generator
.emitNode(base
.get(), m_expr
);
1534 RefPtr
<RegisterID
> i
= generator
.newTemporary();
1535 RefPtr
<RegisterID
> size
= generator
.newTemporary();
1536 RefPtr
<RegisterID
> expectedSubscript
;
1537 RefPtr
<RegisterID
> iter
= generator
.emitGetPropertyNames(generator
.newTemporary(), base
.get(), i
.get(), size
.get(), scope
->breakTarget());
1538 generator
.emitJump(scope
->continueTarget());
1540 RefPtr
<Label
> loopStart
= generator
.newLabel();
1541 generator
.emitLabel(loopStart
.get());
1543 RegisterID
* propertyName
;
1544 bool optimizedForinAccess
= false;
1545 if (m_lexpr
->isResolveNode()) {
1546 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1547 propertyName
= generator
.registerFor(ident
);
1548 if (!propertyName
) {
1549 propertyName
= generator
.newTemporary();
1550 RefPtr
<RegisterID
> protect
= propertyName
;
1551 RegisterID
* base
= generator
.emitResolveBase(generator
.newTemporary(), ident
);
1553 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1554 generator
.emitPutById(base
, ident
, propertyName
);
1556 expectedSubscript
= generator
.emitMove(generator
.newTemporary(), propertyName
);
1557 generator
.pushOptimisedForIn(expectedSubscript
.get(), iter
.get(), i
.get(), propertyName
);
1558 optimizedForinAccess
= true;
1560 } else if (m_lexpr
->isDotAccessorNode()) {
1561 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1562 const Identifier
& ident
= assignNode
->identifier();
1563 propertyName
= generator
.newTemporary();
1564 RefPtr
<RegisterID
> protect
= propertyName
;
1565 RegisterID
* base
= generator
.emitNode(assignNode
->base());
1567 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1568 generator
.emitPutById(base
, ident
, propertyName
);
1570 ASSERT(m_lexpr
->isBracketAccessorNode());
1571 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1572 propertyName
= generator
.newTemporary();
1573 RefPtr
<RegisterID
> protect
= propertyName
;
1574 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1575 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1577 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1578 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
1581 generator
.emitNode(dst
, m_statement
);
1583 if (optimizedForinAccess
)
1584 generator
.popOptimisedForIn();
1586 generator
.emitLabel(scope
->continueTarget());
1587 generator
.emitNextPropertyName(propertyName
, base
.get(), i
.get(), size
.get(), iter
.get(), loopStart
.get());
1588 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1589 generator
.emitLabel(scope
->breakTarget());
1593 // ------------------------------ ContinueNode ---------------------------------
1596 RegisterID
* ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1598 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1600 LabelScope
* scope
= generator
.continueTarget(m_ident
);
1603 return m_ident
.isEmpty()
1604 ? emitThrowError(generator
, SyntaxError
, "Invalid continue statement.")
1605 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1607 generator
.emitJumpScopes(scope
->continueTarget(), scope
->scopeDepth());
1611 // ------------------------------ BreakNode ------------------------------------
1614 RegisterID
* BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1616 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1618 LabelScope
* scope
= generator
.breakTarget(m_ident
);
1621 return m_ident
.isEmpty()
1622 ? emitThrowError(generator
, SyntaxError
, "Invalid break statement.")
1623 : emitThrowError(generator
, SyntaxError
, "Undefined label: '%s'.", m_ident
);
1625 generator
.emitJumpScopes(scope
->breakTarget(), scope
->scopeDepth());
1629 // ------------------------------ ReturnNode -----------------------------------
1631 RegisterID
* ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1633 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1634 if (generator
.codeType() != FunctionCode
)
1635 return emitThrowError(generator
, SyntaxError
, "Invalid return statement.");
1637 if (dst
== generator
.ignoredResult())
1639 RegisterID
* r0
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
1640 RefPtr
<RegisterID
> returnRegister
;
1641 if (generator
.scopeDepth()) {
1642 RefPtr
<Label
> l0
= generator
.newLabel();
1643 if (generator
.hasFinaliser() && !r0
->isTemporary()) {
1644 returnRegister
= generator
.emitMove(generator
.newTemporary(), r0
);
1645 r0
= returnRegister
.get();
1647 generator
.emitJumpScopes(l0
.get(), 0);
1648 generator
.emitLabel(l0
.get());
1650 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1651 return generator
.emitReturn(r0
);
1654 // ------------------------------ WithNode -------------------------------------
1656 RegisterID
* WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1658 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1660 RefPtr
<RegisterID
> scope
= generator
.newTemporary();
1661 generator
.emitNode(scope
.get(), m_expr
); // scope must be protected until popped
1662 generator
.emitExpressionInfo(m_divot
, m_expressionLength
, 0);
1663 generator
.emitPushScope(scope
.get());
1664 RegisterID
* result
= generator
.emitNode(dst
, m_statement
);
1665 generator
.emitPopScope();
1669 // ------------------------------ CaseClauseNode --------------------------------
1671 inline void CaseClauseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1674 m_statements
->emitBytecode(generator
, dst
);
1677 // ------------------------------ CaseBlockNode --------------------------------
1686 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
1688 for (; list
; list
= list
->getNext()) {
1689 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
1690 literalVector
.append(clauseExpression
);
1691 if (clauseExpression
->isNumber()) {
1692 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
1693 int32_t intVal
= static_cast<int32_t>(value
);
1694 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
1695 typeForTable
= SwitchNeither
;
1698 if (intVal
< min_num
)
1700 if (intVal
> max_num
)
1702 typeForTable
= SwitchNumber
;
1705 if (clauseExpression
->isString()) {
1706 if (typeForTable
& ~SwitchString
) {
1707 typeForTable
= SwitchNeither
;
1710 const UString
& value
= static_cast<StringNode
*>(clauseExpression
)->value().ustring();
1711 if (singleCharacterSwitch
&= value
.size() == 1) {
1712 int32_t intVal
= value
.rep()->characters()[0];
1713 if (intVal
< min_num
)
1715 if (intVal
> max_num
)
1718 typeForTable
= SwitchString
;
1721 typeForTable
= SwitchNeither
;
1726 SwitchInfo::SwitchType
CaseBlockNode::tryOptimizedSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
1728 SwitchKind typeForTable
= SwitchUnset
;
1729 bool singleCharacterSwitch
= true;
1731 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1732 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1734 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
1735 return SwitchInfo::SwitchNone
;
1737 if (typeForTable
== SwitchNumber
) {
1738 int32_t range
= max_num
- min_num
;
1739 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1740 return SwitchInfo::SwitchImmediate
;
1741 return SwitchInfo::SwitchNone
;
1744 ASSERT(typeForTable
== SwitchString
);
1746 if (singleCharacterSwitch
) {
1747 int32_t range
= max_num
- min_num
;
1748 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1749 return SwitchInfo::SwitchCharacter
;
1752 return SwitchInfo::SwitchString
;
1755 RegisterID
* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
1757 RefPtr
<Label
> defaultLabel
;
1758 Vector
<RefPtr
<Label
>, 8> labelVector
;
1759 Vector
<ExpressionNode
*, 8> literalVector
;
1760 int32_t min_num
= std::numeric_limits
<int32_t>::max();
1761 int32_t max_num
= std::numeric_limits
<int32_t>::min();
1762 SwitchInfo::SwitchType switchType
= tryOptimizedSwitch(literalVector
, min_num
, max_num
);
1764 if (switchType
!= SwitchInfo::SwitchNone
) {
1765 // Prepare the various labels
1766 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
1767 labelVector
.append(generator
.newLabel());
1768 defaultLabel
= generator
.newLabel();
1769 generator
.beginSwitch(switchExpression
, switchType
);
1772 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1773 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1774 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1775 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1776 labelVector
.append(generator
.newLabel());
1777 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1780 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1781 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1782 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1783 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1784 labelVector
.append(generator
.newLabel());
1785 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1787 defaultLabel
= generator
.newLabel();
1788 generator
.emitJump(defaultLabel
.get());
1791 RegisterID
* result
= 0;
1794 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1795 generator
.emitLabel(labelVector
[i
++].get());
1796 list
->getClause()->emitBytecode(generator
, dst
);
1799 if (m_defaultClause
) {
1800 generator
.emitLabel(defaultLabel
.get());
1801 m_defaultClause
->emitBytecode(generator
, dst
);
1804 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1805 generator
.emitLabel(labelVector
[i
++].get());
1806 list
->getClause()->emitBytecode(generator
, dst
);
1808 if (!m_defaultClause
)
1809 generator
.emitLabel(defaultLabel
.get());
1811 ASSERT(i
== labelVector
.size());
1812 if (switchType
!= SwitchInfo::SwitchNone
) {
1813 ASSERT(labelVector
.size() == literalVector
.size());
1814 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
1819 // ------------------------------ SwitchNode -----------------------------------
1821 RegisterID
* SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1823 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1825 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Switch
);
1827 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
1828 RegisterID
* r1
= m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
1830 generator
.emitLabel(scope
->breakTarget());
1834 // ------------------------------ LabelNode ------------------------------------
1836 RegisterID
* LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1838 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1840 if (generator
.breakTarget(m_name
))
1841 return emitThrowError(generator
, SyntaxError
, "Duplicate label: %s.", m_name
);
1843 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
1844 RegisterID
* r0
= generator
.emitNode(dst
, m_statement
);
1846 generator
.emitLabel(scope
->breakTarget());
1850 // ------------------------------ ThrowNode ------------------------------------
1852 RegisterID
* ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1854 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1856 if (dst
== generator
.ignoredResult())
1858 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
1859 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1860 generator
.emitThrow(expr
.get());
1864 // ------------------------------ TryNode --------------------------------------
1866 RegisterID
* TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1868 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1869 // optimizer knows they may be jumped to from anywhere.
1871 IncreaseEmitNodeDepth
stackGuard(generator
);
1873 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1875 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
1876 RefPtr
<Label
> finallyStart
;
1877 RefPtr
<RegisterID
> finallyReturnAddr
;
1878 if (m_finallyBlock
) {
1879 finallyStart
= generator
.newLabel();
1880 finallyReturnAddr
= generator
.newTemporary();
1881 generator
.pushFinallyContext(finallyStart
.get(), finallyReturnAddr
.get());
1884 generator
.emitLabel(tryStartLabel
.get());
1885 generator
.emitNode(dst
, m_tryBlock
);
1888 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
1890 // Normal path: jump over the catch block.
1891 generator
.emitJump(catchEndLabel
.get());
1893 // Uncaught exception path: the catch block.
1894 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1895 RefPtr
<RegisterID
> exceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1896 if (m_catchHasEval
) {
1897 RefPtr
<RegisterID
> dynamicScopeObject
= generator
.emitNewObject(generator
.newTemporary());
1898 generator
.emitPutById(dynamicScopeObject
.get(), m_exceptionIdent
, exceptionRegister
.get());
1899 generator
.emitMove(exceptionRegister
.get(), dynamicScopeObject
.get());
1900 generator
.emitPushScope(exceptionRegister
.get());
1902 generator
.emitPushNewScope(exceptionRegister
.get(), m_exceptionIdent
, exceptionRegister
.get());
1903 generator
.emitNode(dst
, m_catchBlock
);
1904 generator
.emitPopScope();
1905 generator
.emitLabel(catchEndLabel
.get());
1908 if (m_finallyBlock
) {
1909 generator
.popFinallyContext();
1910 // there may be important registers live at the time we jump
1911 // to a finally block (such as for a return or throw) so we
1912 // ref the highest register ever used as a conservative
1913 // approach to not clobbering anything important
1914 RefPtr
<RegisterID
> highestUsedRegister
= generator
.highestUsedRegister();
1915 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
1917 // Normal path: invoke the finally block, then jump over it.
1918 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1919 generator
.emitJump(finallyEndLabel
.get());
1921 // Uncaught exception path: invoke the finally block, then re-throw the exception.
1922 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1923 RefPtr
<RegisterID
> tempExceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1924 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1925 generator
.emitThrow(tempExceptionRegister
.get());
1927 // The finally block.
1928 generator
.emitLabel(finallyStart
.get());
1929 generator
.emitNode(dst
, m_finallyBlock
);
1930 generator
.emitSubroutineReturn(finallyReturnAddr
.get());
1932 generator
.emitLabel(finallyEndLabel
.get());
1938 // ------------------------------ ScopeNode -----------------------------
1940 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1942 if (m_data
->m_statements
)
1943 m_data
->m_statements
->emitBytecode(generator
, dst
);
1946 // ------------------------------ ProgramNode -----------------------------
1948 RegisterID
* ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1950 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1952 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1953 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1954 emitStatementsBytecode(generator
, dstRegister
.get());
1956 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1957 generator
.emitEnd(dstRegister
.get());
1961 // ------------------------------ EvalNode -----------------------------
1963 RegisterID
* EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1965 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1967 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1968 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1969 emitStatementsBytecode(generator
, dstRegister
.get());
1971 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1972 generator
.emitEnd(dstRegister
.get());
1976 // ------------------------------ FunctionBodyNode -----------------------------
1978 RegisterID
* FunctionBodyNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1980 generator
.emitDebugHook(DidEnterCallFrame
, firstLine(), lastLine());
1981 emitStatementsBytecode(generator
, generator
.ignoredResult());
1982 StatementNode
* singleStatement
= this->singleStatement();
1983 if (singleStatement
&& singleStatement
->isBlock()) {
1984 StatementNode
* lastStatementInBlock
= static_cast<BlockNode
*>(singleStatement
)->lastStatement();
1985 if (lastStatementInBlock
&& lastStatementInBlock
->isReturnNode())
1989 RegisterID
* r0
= generator
.emitLoad(0, jsUndefined());
1990 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1991 generator
.emitReturn(r0
);
1995 // ------------------------------ FuncDeclNode ---------------------------------
1997 RegisterID
* FuncDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1999 if (dst
== generator
.ignoredResult())
2004 // ------------------------------ FuncExprNode ---------------------------------
2006 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2008 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);