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, 2012, 2013 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>
8 * Copyright (C) 2012 Igalia, S.L.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
29 #include "NodeConstructors.h"
31 #include "BytecodeGenerator.h"
32 #include "CallFrame.h"
35 #include "JSFunction.h"
36 #include "JSGlobalObject.h"
37 #include "JSNameScope.h"
38 #include "LabelScope.h"
40 #include "Operations.h"
42 #include "PropertyNameArray.h"
43 #include "RegExpCache.h"
44 #include "RegExpObject.h"
45 #include "SamplingTool.h"
46 #include <wtf/Assertions.h>
47 #include <wtf/RefCountedLeakCounter.h>
48 #include <wtf/Threading.h>
55 Details of the emitBytecode function.
57 Return value: The register holding the production's value.
58 dst: An optional parameter specifying the most efficient destination at
59 which to store the production's value. The callee must honor dst.
61 The dst argument provides for a crude form of copy propagation. For example,
74 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
77 void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
79 RegisterID
* result
= generator
.emitNode(this);
80 if (fallThroughMode
== FallThroughMeansTrue
)
81 generator
.emitJumpIfFalse(result
, falseTarget
);
83 generator
.emitJumpIfTrue(result
, trueTarget
);
86 // ------------------------------ ThrowableExpressionData --------------------------------
88 RegisterID
* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator
& generator
, const String
& message
)
90 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
91 generator
.emitThrowReferenceError(message
);
92 return generator
.newTemporary();
95 // ------------------------------ ConstantNode ----------------------------------
97 void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
99 TriState value
= jsValue(generator
).pureToBoolean();
100 if (value
== MixedTriState
)
101 ExpressionNode::emitBytecodeInConditionContext(generator
, trueTarget
, falseTarget
, fallThroughMode
);
102 else if (value
== TrueTriState
&& fallThroughMode
== FallThroughMeansFalse
)
103 generator
.emitJump(trueTarget
);
104 else if (value
== FalseTriState
&& fallThroughMode
== FallThroughMeansTrue
)
105 generator
.emitJump(falseTarget
);
107 // All other cases are unconditional fall-throughs, like "if (true)".
110 RegisterID
* ConstantNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
112 if (dst
== generator
.ignoredResult())
114 return generator
.emitLoad(dst
, jsValue(generator
));
117 JSValue
StringNode::jsValue(BytecodeGenerator
& generator
) const
119 return generator
.addStringConstant(m_value
);
122 // ------------------------------ RegExpNode -----------------------------------
124 RegisterID
* RegExpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
126 if (dst
== generator
.ignoredResult())
128 return generator
.emitNewRegExp(generator
.finalDestination(dst
), RegExp::create(*generator
.vm(), m_pattern
.string(), regExpFlags(m_flags
.string())));
131 // ------------------------------ ThisNode -------------------------------------
133 RegisterID
* ThisNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
135 if (dst
== generator
.ignoredResult())
137 return generator
.moveToDestinationIfNeeded(dst
, generator
.thisRegister());
140 // ------------------------------ ResolveNode ----------------------------------
142 bool ResolveNode::isPure(BytecodeGenerator
& generator
) const
144 return generator
.resolve(m_ident
).isStatic();
147 RegisterID
* ResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
149 ResolveResult resolveResult
= generator
.resolve(m_ident
);
150 if (RegisterID
* local
= resolveResult
.local()) {
151 if (dst
== generator
.ignoredResult())
153 return generator
.moveToDestinationIfNeeded(dst
, local
);
156 unsigned divot
= m_startOffset
+ m_ident
.length();
157 generator
.emitExpressionInfo(divot
, m_ident
.length(), 0, m_divotLine
, m_divotLineStart
);
158 return generator
.emitResolve(generator
.finalDestination(dst
), resolveResult
, m_ident
);
161 // ------------------------------ ArrayNode ------------------------------------
163 RegisterID
* ArrayNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
165 // FIXME: Should we put all of this code into emitNewArray?
168 ElementNode
* firstPutElement
;
169 for (firstPutElement
= m_element
; firstPutElement
; firstPutElement
= firstPutElement
->next()) {
170 if (firstPutElement
->elision())
175 if (!firstPutElement
&& !m_elision
)
176 return generator
.emitNewArray(generator
.finalDestination(dst
), m_element
, length
);
178 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.tempDestination(dst
), m_element
, length
);
180 for (ElementNode
* n
= firstPutElement
; n
; n
= n
->next()) {
181 RegisterID
* value
= generator
.emitNode(n
->value());
182 length
+= n
->elision();
183 generator
.emitPutByIndex(array
.get(), length
++, value
);
187 RegisterID
* value
= generator
.emitLoad(0, jsNumber(m_elision
+ length
));
188 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, value
);
191 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
194 bool ArrayNode::isSimpleArray() const
196 if (m_elision
|| m_optional
)
198 for (ElementNode
* ptr
= m_element
; ptr
; ptr
= ptr
->next()) {
205 ArgumentListNode
* ArrayNode::toArgumentList(VM
* vm
, int lineNumber
, int startPosition
) const
207 ASSERT(!m_elision
&& !m_optional
);
208 ElementNode
* ptr
= m_element
;
211 JSTokenLocation location
;
212 location
.line
= lineNumber
;
213 location
.startOffset
= startPosition
;
214 ArgumentListNode
* head
= new (vm
) ArgumentListNode(location
, ptr
->value());
215 ArgumentListNode
* tail
= head
;
217 for (; ptr
; ptr
= ptr
->next()) {
218 ASSERT(!ptr
->elision());
219 tail
= new (vm
) ArgumentListNode(location
, tail
, ptr
->value());
224 // ------------------------------ ObjectLiteralNode ----------------------------
226 RegisterID
* ObjectLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
229 if (dst
== generator
.ignoredResult())
231 return generator
.emitNewObject(generator
.finalDestination(dst
));
233 return generator
.emitNode(dst
, m_list
);
236 // ------------------------------ PropertyListNode -----------------------------
238 RegisterID
* PropertyListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
240 RefPtr
<RegisterID
> newObj
= generator
.tempDestination(dst
);
242 generator
.emitNewObject(newObj
.get());
244 // Fast case: this loop just handles regular value properties.
245 PropertyListNode
* p
= this;
246 for (; p
&& p
->m_node
->m_type
== PropertyNode::Constant
; p
= p
->m_next
)
247 generator
.emitDirectPutById(newObj
.get(), p
->m_node
->name(), generator
.emitNode(p
->m_node
->m_assign
));
249 // Were there any get/set properties?
251 typedef std::pair
<PropertyNode
*, PropertyNode
*> GetterSetterPair
;
252 typedef HashMap
<StringImpl
*, GetterSetterPair
> GetterSetterMap
;
255 // Build a map, pairing get/set values together.
256 for (PropertyListNode
* q
= p
; q
; q
= q
->m_next
) {
257 PropertyNode
* node
= q
->m_node
;
258 if (node
->m_type
== PropertyNode::Constant
)
261 GetterSetterPair
pair(node
, static_cast<PropertyNode
*>(0));
262 GetterSetterMap::AddResult result
= map
.add(node
->name().impl(), pair
);
263 if (!result
.isNewEntry
)
264 result
.iterator
->value
.second
= node
;
267 // Iterate over the remaining properties in the list.
268 for (; p
; p
= p
->m_next
) {
269 PropertyNode
* node
= p
->m_node
;
270 RegisterID
* value
= generator
.emitNode(node
->m_assign
);
272 // Handle regular values.
273 if (node
->m_type
== PropertyNode::Constant
) {
274 generator
.emitDirectPutById(newObj
.get(), node
->name(), value
);
278 // This is a get/set property, find its entry in the map.
279 ASSERT(node
->m_type
== PropertyNode::Getter
|| node
->m_type
== PropertyNode::Setter
);
280 GetterSetterMap::iterator it
= map
.find(node
->name().impl());
281 ASSERT(it
!= map
.end());
282 GetterSetterPair
& pair
= it
->value
;
284 // Was this already generated as a part of its partner?
285 if (pair
.second
== node
)
288 // Generate the paired node now.
289 RefPtr
<RegisterID
> getterReg
;
290 RefPtr
<RegisterID
> setterReg
;
292 if (node
->m_type
== PropertyNode::Getter
) {
295 ASSERT(pair
.second
->m_type
== PropertyNode::Setter
);
296 setterReg
= generator
.emitNode(pair
.second
->m_assign
);
298 setterReg
= generator
.newTemporary();
299 generator
.emitLoad(setterReg
.get(), jsUndefined());
302 ASSERT(node
->m_type
== PropertyNode::Setter
);
305 ASSERT(pair
.second
->m_type
== PropertyNode::Getter
);
306 getterReg
= generator
.emitNode(pair
.second
->m_assign
);
308 getterReg
= generator
.newTemporary();
309 generator
.emitLoad(getterReg
.get(), jsUndefined());
313 generator
.emitPutGetterSetter(newObj
.get(), node
->name(), getterReg
.get(), setterReg
.get());
317 return generator
.moveToDestinationIfNeeded(dst
, newObj
.get());
320 // ------------------------------ BracketAccessorNode --------------------------------
322 RegisterID
* BracketAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
324 if (m_base
->isResolveNode()
325 && generator
.willResolveToArguments(static_cast<ResolveNode
*>(m_base
)->identifier())
326 && !generator
.symbolTable().slowArguments()) {
327 RegisterID
* property
= generator
.emitNode(m_subscript
);
328 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
329 return generator
.emitGetArgumentByVal(generator
.finalDestination(dst
), generator
.uncheckedRegisterForArguments(), property
);
332 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
, m_subscript
->isPure(generator
));
333 RegisterID
* property
= generator
.emitNode(m_subscript
);
334 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
335 return generator
.emitGetByVal(generator
.finalDestination(dst
), base
.get(), property
);
338 // ------------------------------ DotAccessorNode --------------------------------
340 RegisterID
* DotAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
342 if (m_ident
== generator
.propertyNames().length
) {
343 if (!m_base
->isResolveNode())
344 goto nonArgumentsPath
;
345 ResolveNode
* resolveNode
= static_cast<ResolveNode
*>(m_base
);
346 if (!generator
.willResolveToArguments(resolveNode
->identifier()))
347 goto nonArgumentsPath
;
348 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
349 return generator
.emitGetArgumentsLength(generator
.finalDestination(dst
), generator
.uncheckedRegisterForArguments());
353 RegisterID
* base
= generator
.emitNode(m_base
);
354 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
355 return generator
.emitGetById(generator
.finalDestination(dst
), base
, m_ident
);
358 // ------------------------------ ArgumentListNode -----------------------------
360 RegisterID
* ArgumentListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
363 return generator
.emitNode(dst
, m_expr
);
366 // ------------------------------ NewExprNode ----------------------------------
368 RegisterID
* NewExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
370 ExpectedFunction expectedFunction
;
371 if (m_expr
->isResolveNode())
372 expectedFunction
= generator
.expectedFunctionForIdentifier(static_cast<ResolveNode
*>(m_expr
)->identifier());
374 expectedFunction
= NoExpectedFunction
;
375 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
376 CallArguments
callArguments(generator
, m_args
);
377 return generator
.emitConstruct(generator
.finalDestinationOrIgnored(dst
), func
.get(), expectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
380 inline CallArguments::CallArguments(BytecodeGenerator
& generator
, ArgumentsNode
* argumentsNode
)
381 : m_argumentsNode(argumentsNode
)
383 if (generator
.shouldEmitProfileHooks())
384 m_profileHookRegister
= generator
.newTemporary();
386 size_t argumentCountIncludingThis
= 1; // 'this' register.
388 for (ArgumentListNode
* node
= argumentsNode
->m_listNode
; node
; node
= node
->m_next
)
389 ++argumentCountIncludingThis
;
392 m_argv
.grow(argumentCountIncludingThis
);
393 for (int i
= argumentCountIncludingThis
- 1; i
>= 0; --i
) {
394 m_argv
[i
] = generator
.newTemporary();
395 ASSERT(static_cast<size_t>(i
) == m_argv
.size() - 1 || m_argv
[i
]->index() == m_argv
[i
+ 1]->index() + 1);
399 inline void CallArguments::newArgument(BytecodeGenerator
& generator
)
401 RefPtr
<RegisterID
> tmp
= generator
.newTemporary();
402 ASSERT(m_argv
.isEmpty() || tmp
->index() == m_argv
.last()->index() + 1); // Calling convention assumes that all arguments are contiguous.
403 m_argv
.append(tmp
.release());
406 // ------------------------------ EvalFunctionCallNode ----------------------------------
408 RegisterID
* EvalFunctionCallNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
410 RefPtr
<RegisterID
> func
= generator
.tempDestination(dst
);
411 CallArguments
callArguments(generator
, m_args
);
412 generator
.emitExpressionInfo(divot() - divotStartOffset() + 4, 4, 0, divotLine(), divotLineStart());
413 generator
.emitResolveWithThis(callArguments
.thisRegister(), func
.get(), generator
.resolve(generator
.propertyNames().eval
), generator
.propertyNames().eval
);
414 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
417 // ------------------------------ FunctionCallValueNode ----------------------------------
419 RegisterID
* FunctionCallValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
421 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
422 CallArguments
callArguments(generator
, m_args
);
423 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
424 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, func
.get()), func
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
427 // ------------------------------ FunctionCallResolveNode ----------------------------------
429 RegisterID
* FunctionCallResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
431 ExpectedFunction expectedFunction
= generator
.expectedFunctionForIdentifier(m_ident
);
432 ResolveResult resolveResult
= generator
.resolve(m_ident
);
434 if (RegisterID
* local
= resolveResult
.local()) {
435 RefPtr
<RegisterID
> func
= generator
.emitMove(generator
.tempDestination(dst
), local
);
436 CallArguments
callArguments(generator
, m_args
);
437 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
438 // This passes NoExpectedFunction because we expect that if the function is in a
439 // local variable, then it's not one of our built-in constructors.
440 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, callArguments
.thisRegister()), func
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
443 if (resolveResult
.isStatic()) {
444 RefPtr
<RegisterID
> func
= generator
.newTemporary();
445 CallArguments
callArguments(generator
, m_args
);
446 generator
.emitGetStaticVar(func
.get(), resolveResult
, m_ident
);
447 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
448 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, func
.get()), func
.get(), expectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
451 RefPtr
<RegisterID
> func
= generator
.newTemporary();
452 CallArguments
callArguments(generator
, m_args
);
453 int identifierStart
= divot() - divotStartOffset();
455 generator
.emitExpressionInfo(identifierStart
+ m_ident
.length(), m_ident
.length(), 0, divotLine(), divotLineStart());
456 generator
.emitResolveWithThis(callArguments
.thisRegister(), func
.get(), resolveResult
, m_ident
);
457 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, func
.get()), func
.get(), expectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
460 // ------------------------------ FunctionCallBracketNode ----------------------------------
462 RegisterID
* FunctionCallBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
464 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
465 RegisterID
* property
= generator
.emitNode(m_subscript
);
466 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
467 RefPtr
<RegisterID
> function
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
);
468 CallArguments
callArguments(generator
, m_args
);
469 generator
.emitMove(callArguments
.thisRegister(), base
.get());
470 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, function
.get()), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
473 // ------------------------------ FunctionCallDotNode ----------------------------------
475 RegisterID
* FunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
477 RefPtr
<RegisterID
> function
= generator
.tempDestination(dst
);
478 CallArguments
callArguments(generator
, m_args
);
479 generator
.emitNode(callArguments
.thisRegister(), m_base
);
480 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
481 generator
.emitGetById(function
.get(), callArguments
.thisRegister(), m_ident
);
482 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, function
.get()), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
485 RegisterID
* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
487 RefPtr
<Label
> realCall
= generator
.newLabel();
488 RefPtr
<Label
> end
= generator
.newLabel();
489 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
490 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
491 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
492 RefPtr
<RegisterID
> finalDestinationOrIgnored
= generator
.finalDestinationOrIgnored(dst
, function
.get());
493 generator
.emitJumpIfNotFunctionCall(function
.get(), realCall
.get());
495 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
496 ArgumentListNode
* oldList
= m_args
->m_listNode
;
497 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
499 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
500 CallArguments
callArguments(generator
, m_args
);
501 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
502 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
503 generator
.emitJump(end
.get());
505 m_args
->m_listNode
= oldList
;
507 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
508 CallArguments
callArguments(generator
, m_args
);
509 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
510 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
511 generator
.emitJump(end
.get());
514 generator
.emitLabel(realCall
.get());
516 CallArguments
callArguments(generator
, m_args
);
517 generator
.emitMove(callArguments
.thisRegister(), base
.get());
518 generator
.emitCall(finalDestinationOrIgnored
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
520 generator
.emitLabel(end
.get());
521 return finalDestinationOrIgnored
.get();
524 static bool areTrivialApplyArguments(ArgumentsNode
* args
)
526 return !args
->m_listNode
|| !args
->m_listNode
->m_expr
|| !args
->m_listNode
->m_next
527 || (!args
->m_listNode
->m_next
->m_next
&& args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
530 RegisterID
* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
532 // A few simple cases can be trivially handled as ordinary function calls.
533 // function.apply(), function.apply(arg) -> identical to function.call
534 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
535 bool mayBeCall
= areTrivialApplyArguments(m_args
);
537 RefPtr
<Label
> realCall
= generator
.newLabel();
538 RefPtr
<Label
> end
= generator
.newLabel();
539 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
540 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
541 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
542 RefPtr
<RegisterID
> finalDestinationOrIgnored
= generator
.finalDestinationOrIgnored(dst
, function
.get());
543 generator
.emitJumpIfNotFunctionApply(function
.get(), realCall
.get());
546 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
547 ArgumentListNode
* oldList
= m_args
->m_listNode
;
548 if (m_args
->m_listNode
->m_next
) {
549 ASSERT(m_args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
550 ASSERT(!m_args
->m_listNode
->m_next
->m_next
);
551 m_args
->m_listNode
= static_cast<ArrayNode
*>(m_args
->m_listNode
->m_next
->m_expr
)->toArgumentList(generator
.vm(), 0, 0);
552 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
553 CallArguments
callArguments(generator
, m_args
);
554 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
555 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
557 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
558 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
559 CallArguments
callArguments(generator
, m_args
);
560 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
561 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
563 m_args
->m_listNode
= oldList
;
565 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
566 CallArguments
callArguments(generator
, m_args
);
567 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
568 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
571 ASSERT(m_args
->m_listNode
&& m_args
->m_listNode
->m_next
);
572 RefPtr
<RegisterID
> profileHookRegister
;
573 if (generator
.shouldEmitProfileHooks())
574 profileHookRegister
= generator
.newTemporary();
575 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
576 RefPtr
<RegisterID
> thisRegister
= generator
.emitNode(m_args
->m_listNode
->m_expr
);
577 RefPtr
<RegisterID
> argsRegister
;
578 ArgumentListNode
* args
= m_args
->m_listNode
->m_next
;
579 if (args
->m_expr
->isResolveNode() && generator
.willResolveToArguments(static_cast<ResolveNode
*>(args
->m_expr
)->identifier()))
580 argsRegister
= generator
.uncheckedRegisterForArguments();
582 argsRegister
= generator
.emitNode(args
->m_expr
);
584 // Function.prototype.apply ignores extra arguments, but we still
585 // need to evaluate them for side effects.
586 while ((args
= args
->m_next
))
587 generator
.emitNode(args
->m_expr
);
589 generator
.emitCallVarargs(finalDestinationOrIgnored
.get(), realFunction
.get(), thisRegister
.get(), argsRegister
.get(), generator
.newTemporary(), profileHookRegister
.get(), divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
591 generator
.emitJump(end
.get());
593 generator
.emitLabel(realCall
.get());
595 CallArguments
callArguments(generator
, m_args
);
596 generator
.emitMove(callArguments
.thisRegister(), base
.get());
597 generator
.emitCall(finalDestinationOrIgnored
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
599 generator
.emitLabel(end
.get());
600 return finalDestinationOrIgnored
.get();
603 // ------------------------------ PostfixNode ----------------------------------
605 static RegisterID
* emitIncOrDec(BytecodeGenerator
& generator
, RegisterID
* srcDst
, Operator oper
)
607 return (oper
== OpPlusPlus
) ? generator
.emitInc(srcDst
) : generator
.emitDec(srcDst
);
610 static RegisterID
* emitPostIncOrDec(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* srcDst
, Operator oper
)
613 return generator
.emitToNumber(generator
.finalDestination(dst
), srcDst
);
614 RefPtr
<RegisterID
> tmp
= generator
.emitToNumber(generator
.tempDestination(dst
), srcDst
);
615 emitIncOrDec(generator
, srcDst
, oper
);
616 return generator
.moveToDestinationIfNeeded(dst
, tmp
.get());
619 RegisterID
* PostfixNode::emitResolve(BytecodeGenerator
& generator
, RegisterID
* dst
)
621 if (dst
== generator
.ignoredResult())
622 return PrefixNode::emitResolve(generator
, dst
);
624 ASSERT(m_expr
->isResolveNode());
625 ResolveNode
* resolve
= static_cast<ResolveNode
*>(m_expr
);
626 const Identifier
& ident
= resolve
->identifier();
628 ResolveResult resolveResult
= generator
.resolve(ident
);
630 if (RefPtr
<RegisterID
> local
= resolveResult
.local()) {
631 if (resolveResult
.isReadOnly()) {
632 generator
.emitReadOnlyExceptionIfNeeded();
633 local
= generator
.emitMove(generator
.tempDestination(dst
), local
.get());
635 return emitPostIncOrDec(generator
, generator
.finalDestination(dst
), local
.get(), m_operator
);
638 if (resolveResult
.isStatic() && !resolveResult
.isReadOnly()) {
639 RefPtr
<RegisterID
> value
= generator
.emitGetStaticVar(generator
.newTemporary(), resolveResult
, ident
);
640 RefPtr
<RegisterID
> oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
641 generator
.emitPutStaticVar(resolveResult
, ident
, value
.get());
642 return oldValue
.get();
645 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
646 RefPtr
<RegisterID
> value
= generator
.newTemporary();
647 NonlocalResolveInfo resolveInfo
;
648 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBaseForPut(generator
.newTemporary(), value
.get(), resolveResult
, ident
, resolveInfo
);
649 RefPtr
<RegisterID
> oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
650 generator
.emitPutToBase(base
.get(), ident
, value
.get(), resolveInfo
);
651 return oldValue
.get();
654 RegisterID
* PostfixNode::emitBracket(BytecodeGenerator
& generator
, RegisterID
* dst
)
656 if (dst
== generator
.ignoredResult())
657 return PrefixNode::emitBracket(generator
, dst
);
659 ASSERT(m_expr
->isBracketAccessorNode());
660 BracketAccessorNode
* bracketAccessor
= static_cast<BracketAccessorNode
*>(m_expr
);
661 ExpressionNode
* baseNode
= bracketAccessor
->base();
662 ExpressionNode
* subscript
= bracketAccessor
->subscript();
664 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(baseNode
, bracketAccessor
->subscriptHasAssignments(), subscript
->isPure(generator
));
665 RefPtr
<RegisterID
> property
= generator
.emitNode(subscript
);
667 generator
.emitExpressionInfo(bracketAccessor
->divot(), bracketAccessor
->divotStartOffset(), bracketAccessor
->divotEndOffset(), bracketAccessor
->divotLine(), bracketAccessor
->divotLineStart());
668 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.newTemporary(), base
.get(), property
.get());
669 RegisterID
* oldValue
= emitPostIncOrDec(generator
, generator
.tempDestination(dst
), value
.get(), m_operator
);
670 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
671 generator
.emitPutByVal(base
.get(), property
.get(), value
.get());
672 return generator
.moveToDestinationIfNeeded(dst
, oldValue
);
675 RegisterID
* PostfixNode::emitDot(BytecodeGenerator
& generator
, RegisterID
* dst
)
677 if (dst
== generator
.ignoredResult())
678 return PrefixNode::emitDot(generator
, dst
);
680 ASSERT(m_expr
->isDotAccessorNode());
681 DotAccessorNode
* dotAccessor
= static_cast<DotAccessorNode
*>(m_expr
);
682 ExpressionNode
* baseNode
= dotAccessor
->base();
683 const Identifier
& ident
= dotAccessor
->identifier();
685 RefPtr
<RegisterID
> base
= generator
.emitNode(baseNode
);
687 generator
.emitExpressionInfo(dotAccessor
->divot(), dotAccessor
->divotStartOffset(), dotAccessor
->divotEndOffset(), dotAccessor
->divotLine(), dotAccessor
->divotLineStart());
688 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.newTemporary(), base
.get(), ident
);
689 RegisterID
* oldValue
= emitPostIncOrDec(generator
, generator
.tempDestination(dst
), value
.get(), m_operator
);
690 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
691 generator
.emitPutById(base
.get(), ident
, value
.get());
692 return generator
.moveToDestinationIfNeeded(dst
, oldValue
);
695 RegisterID
* PostfixNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
697 if (m_expr
->isResolveNode())
698 return emitResolve(generator
, dst
);
700 if (m_expr
->isBracketAccessorNode())
701 return emitBracket(generator
, dst
);
703 if (m_expr
->isDotAccessorNode())
704 return emitDot(generator
, dst
);
706 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
707 ? "Postfix ++ operator applied to value that is not a reference."
708 : "Postfix -- operator applied to value that is not a reference.");
711 // ------------------------------ DeleteResolveNode -----------------------------------
713 RegisterID
* DeleteResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
715 ResolveResult resolveResult
= generator
.resolve(m_ident
);
716 if (resolveResult
.isRegister())
717 return generator
.emitLoad(generator
.finalDestination(dst
), false);
719 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
720 RegisterID
* base
= generator
.emitResolveBase(generator
.tempDestination(dst
), resolveResult
, m_ident
);
721 return generator
.emitDeleteById(generator
.finalDestination(dst
, base
), base
, m_ident
);
724 // ------------------------------ DeleteBracketNode -----------------------------------
726 RegisterID
* DeleteBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
728 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
729 RegisterID
* r1
= generator
.emitNode(m_subscript
);
731 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
732 return generator
.emitDeleteByVal(generator
.finalDestination(dst
), r0
.get(), r1
);
735 // ------------------------------ DeleteDotNode -----------------------------------
737 RegisterID
* DeleteDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
739 RegisterID
* r0
= generator
.emitNode(m_base
);
741 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
742 return generator
.emitDeleteById(generator
.finalDestination(dst
), r0
, m_ident
);
745 // ------------------------------ DeleteValueNode -----------------------------------
747 RegisterID
* DeleteValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
749 generator
.emitNode(generator
.ignoredResult(), m_expr
);
751 // delete on a non-location expression ignores the value and returns true
752 return generator
.emitLoad(generator
.finalDestination(dst
), true);
755 // ------------------------------ VoidNode -------------------------------------
757 RegisterID
* VoidNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
759 if (dst
== generator
.ignoredResult()) {
760 generator
.emitNode(generator
.ignoredResult(), m_expr
);
763 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
764 return generator
.emitLoad(dst
, jsUndefined());
767 // ------------------------------ TypeOfValueNode -----------------------------------
769 RegisterID
* TypeOfResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
771 ResolveResult resolveResult
= generator
.resolve(m_ident
);
772 if (RegisterID
* local
= resolveResult
.local()) {
773 if (dst
== generator
.ignoredResult())
775 return generator
.emitTypeOf(generator
.finalDestination(dst
), local
);
778 if (resolveResult
.isStatic()) {
779 RefPtr
<RegisterID
> scratch
= generator
.emitGetStaticVar(generator
.tempDestination(dst
), resolveResult
, m_ident
);
780 return generator
.emitTypeOf(generator
.finalDestination(dst
, scratch
.get()), scratch
.get());
783 RefPtr
<RegisterID
> scratch
= generator
.emitResolveBase(generator
.tempDestination(dst
), resolveResult
, m_ident
);
784 generator
.emitGetById(scratch
.get(), scratch
.get(), m_ident
);
785 if (dst
== generator
.ignoredResult())
787 return generator
.emitTypeOf(generator
.finalDestination(dst
, scratch
.get()), scratch
.get());
790 // ------------------------------ TypeOfValueNode -----------------------------------
792 RegisterID
* TypeOfValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
794 if (dst
== generator
.ignoredResult()) {
795 generator
.emitNode(generator
.ignoredResult(), m_expr
);
798 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
799 return generator
.emitTypeOf(generator
.finalDestination(dst
), src
.get());
802 // ------------------------------ PrefixNode ----------------------------------
804 RegisterID
* PrefixNode::emitResolve(BytecodeGenerator
& generator
, RegisterID
* dst
)
806 ASSERT(m_expr
->isResolveNode());
807 ResolveNode
* resolve
= static_cast<ResolveNode
*>(m_expr
);
808 const Identifier
& ident
= resolve
->identifier();
810 ResolveResult resolveResult
= generator
.resolve(ident
);
811 if (RefPtr
<RegisterID
> local
= resolveResult
.local()) {
812 if (resolveResult
.isReadOnly()) {
813 generator
.emitReadOnlyExceptionIfNeeded();
814 local
= generator
.emitMove(generator
.tempDestination(dst
), local
.get());
816 emitIncOrDec(generator
, local
.get(), m_operator
);
817 return generator
.moveToDestinationIfNeeded(dst
, local
.get());
820 if (resolveResult
.isStatic() && !resolveResult
.isReadOnly()) {
821 RefPtr
<RegisterID
> propDst
= generator
.emitGetStaticVar(generator
.tempDestination(dst
), resolveResult
, ident
);
822 emitIncOrDec(generator
, propDst
.get(), m_operator
);
823 generator
.emitPutStaticVar(resolveResult
, ident
, propDst
.get());
824 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
827 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
828 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
829 NonlocalResolveInfo resolveVerifier
;
830 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBaseForPut(generator
.newTemporary(), propDst
.get(), resolveResult
, ident
, resolveVerifier
);
831 emitIncOrDec(generator
, propDst
.get(), m_operator
);
832 generator
.emitPutToBase(base
.get(), ident
, propDst
.get(), resolveVerifier
);
833 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
836 RegisterID
* PrefixNode::emitBracket(BytecodeGenerator
& generator
, RegisterID
* dst
)
838 ASSERT(m_expr
->isBracketAccessorNode());
839 BracketAccessorNode
* bracketAccessor
= static_cast<BracketAccessorNode
*>(m_expr
);
840 ExpressionNode
* baseNode
= bracketAccessor
->base();
841 ExpressionNode
* subscript
= bracketAccessor
->subscript();
843 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(baseNode
, bracketAccessor
->subscriptHasAssignments(), subscript
->isPure(generator
));
844 RefPtr
<RegisterID
> property
= generator
.emitNode(subscript
);
845 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
847 generator
.emitExpressionInfo(bracketAccessor
->divot(), bracketAccessor
->divotStartOffset(), bracketAccessor
->divotEndOffset(), bracketAccessor
->divotLine(), bracketAccessor
->divotLineStart());
848 RegisterID
* value
= generator
.emitGetByVal(propDst
.get(), base
.get(), property
.get());
849 emitIncOrDec(generator
, value
, m_operator
);
850 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
851 generator
.emitPutByVal(base
.get(), property
.get(), value
);
852 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
855 RegisterID
* PrefixNode::emitDot(BytecodeGenerator
& generator
, RegisterID
* dst
)
857 ASSERT(m_expr
->isDotAccessorNode());
858 DotAccessorNode
* dotAccessor
= static_cast<DotAccessorNode
*>(m_expr
);
859 ExpressionNode
* baseNode
= dotAccessor
->base();
860 const Identifier
& ident
= dotAccessor
->identifier();
862 RefPtr
<RegisterID
> base
= generator
.emitNode(baseNode
);
863 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
865 generator
.emitExpressionInfo(dotAccessor
->divot(), dotAccessor
->divotStartOffset(), dotAccessor
->divotEndOffset(), dotAccessor
->divotLine(), dotAccessor
->divotLineStart());
866 RegisterID
* value
= generator
.emitGetById(propDst
.get(), base
.get(), ident
);
867 emitIncOrDec(generator
, value
, m_operator
);
868 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
869 generator
.emitPutById(base
.get(), ident
, value
);
870 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
873 RegisterID
* PrefixNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
875 if (m_expr
->isResolveNode())
876 return emitResolve(generator
, dst
);
878 if (m_expr
->isBracketAccessorNode())
879 return emitBracket(generator
, dst
);
881 if (m_expr
->isDotAccessorNode())
882 return emitDot(generator
, dst
);
884 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
885 ? "Prefix ++ operator applied to value that is not a reference."
886 : "Prefix -- operator applied to value that is not a reference.");
889 // ------------------------------ Unary Operation Nodes -----------------------------------
891 RegisterID
* UnaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
893 RegisterID
* src
= generator
.emitNode(m_expr
);
894 generator
.emitExpressionInfo(startOffset(), 0, 0, lineNo(), lineStartOffset());
895 return generator
.emitUnaryOp(opcodeID(), generator
.finalDestination(dst
), src
);
898 // ------------------------------ BitwiseNotNode -----------------------------------
900 RegisterID
* BitwiseNotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
902 RefPtr
<RegisterID
> src2
= generator
.emitLoad(generator
.newTemporary(), jsNumber(-1));
903 RegisterID
* src1
= generator
.emitNode(m_expr
);
904 return generator
.emitBinaryOp(op_bitxor
, generator
.finalDestination(dst
, src1
), src1
, src2
.get(), OperandTypes(m_expr
->resultDescriptor(), ResultType::numberTypeIsInt32()));
907 // ------------------------------ LogicalNotNode -----------------------------------
909 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
911 // reverse the true and false targets
912 generator
.emitNodeInConditionContext(expr(), falseTarget
, trueTarget
, invert(fallThroughMode
));
916 // ------------------------------ Binary Operation Nodes -----------------------------------
918 // BinaryOpNode::emitStrcat:
920 // This node generates an op_strcat operation. This opcode can handle concatenation of three or
921 // more values, where we can determine a set of separate op_add operations would be operating on
924 // This function expects to be operating on a graph of AST nodes looking something like this:
934 // The assignment operation is optional, if it exists the register holding the value on the
935 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
937 // The method should be called on the node at the root of the tree of regular binary add
938 // operations (marked in the diagram with a double set of parentheses). This node must
939 // be performing a string concatenation (determined by statically detecting that at least
940 // one child must be a string).
942 // Since the minimum number of values being concatenated together is expected to be 3, if
943 // a lhs to a concatenating assignment is not provided then the root add should have at
944 // least one left child that is also an add that can be determined to be operating on strings.
946 RegisterID
* BinaryOpNode::emitStrcat(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* lhs
, ReadModifyResolveNode
* emitExpressionInfoForMe
)
949 ASSERT(resultDescriptor().definitelyIsString());
951 // Create a list of expressions for all the adds in the tree of nodes we can convert into
952 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
953 // added first, and the leftmost child is never added, so the vector produced for the
954 // example above will be [ c, b ].
955 Vector
<ExpressionNode
*, 16> reverseExpressionList
;
956 reverseExpressionList
.append(m_expr2
);
958 // Examine the left child of the add. So long as this is a string add, add its right-child
959 // to the list, and keep processing along the left fork.
960 ExpressionNode
* leftMostAddChild
= m_expr1
;
961 while (leftMostAddChild
->isAdd() && leftMostAddChild
->resultDescriptor().definitelyIsString()) {
962 reverseExpressionList
.append(static_cast<AddNode
*>(leftMostAddChild
)->m_expr2
);
963 leftMostAddChild
= static_cast<AddNode
*>(leftMostAddChild
)->m_expr1
;
966 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
968 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
969 // We could possibly avoid this (the lhs is converted last anyway, we could let the
970 // op_strcat node handle its conversion if required).
972 temporaryRegisters
.append(generator
.newTemporary());
974 // Emit code for the leftmost node ((a) in the example).
975 temporaryRegisters
.append(generator
.newTemporary());
976 RegisterID
* leftMostAddChildTempRegister
= temporaryRegisters
.last().get();
977 generator
.emitNode(leftMostAddChildTempRegister
, leftMostAddChild
);
979 // Note on ordering of conversions:
981 // We maintain the same ordering of conversions as we would see if the concatenations
982 // was performed as a sequence of adds (otherwise this optimization could change
983 // behaviour should an object have been provided a valueOf or toString method).
985 // Considering the above example, the sequnce of execution is:
986 // * evaluate operand (a)
987 // * evaluate operand (b)
988 // * convert (a) to primitive <- (this would be triggered by the first add)
989 // * convert (b) to primitive <- (ditto)
990 // * evaluate operand (c)
991 // * convert (c) to primitive <- (this would be triggered by the second add)
992 // And optionally, if there is an assignment:
993 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
995 // As such we do not plant an op to convert the leftmost child now. Instead, use
996 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
997 // once the second node has been generated. However, if the leftmost child is an
998 // immediate we can trivially determine that no conversion will be required.
999 // If this is the case
1000 if (leftMostAddChild
->isString())
1001 leftMostAddChildTempRegister
= 0;
1003 while (reverseExpressionList
.size()) {
1004 ExpressionNode
* node
= reverseExpressionList
.last();
1005 reverseExpressionList
.removeLast();
1007 // Emit the code for the current node.
1008 temporaryRegisters
.append(generator
.newTemporary());
1009 generator
.emitNode(temporaryRegisters
.last().get(), node
);
1011 // On the first iteration of this loop, when we first reach this point we have just
1012 // generated the second node, which means it is time to convert the leftmost operand.
1013 if (leftMostAddChildTempRegister
) {
1014 generator
.emitToPrimitive(leftMostAddChildTempRegister
, leftMostAddChildTempRegister
);
1015 leftMostAddChildTempRegister
= 0; // Only do this once.
1017 // Plant a conversion for this node, if necessary.
1018 if (!node
->isString())
1019 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
1021 ASSERT(temporaryRegisters
.size() >= 3);
1023 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1024 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1025 if (emitExpressionInfoForMe
)
1026 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->divotStartOffset(), emitExpressionInfoForMe
->divotEndOffset(), emitExpressionInfoForMe
->divotLine(), emitExpressionInfoForMe
->divotLineStart());
1028 // If there is an assignment convert the lhs now. This will also copy lhs to
1029 // the temporary register we allocated for it.
1031 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
1033 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
1036 void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1038 TriState branchCondition
;
1039 ExpressionNode
* branchExpression
;
1040 tryFoldToBranch(generator
, branchCondition
, branchExpression
);
1042 if (branchCondition
== MixedTriState
)
1043 ExpressionNode::emitBytecodeInConditionContext(generator
, trueTarget
, falseTarget
, fallThroughMode
);
1044 else if (branchCondition
== TrueTriState
)
1045 generator
.emitNodeInConditionContext(branchExpression
, trueTarget
, falseTarget
, fallThroughMode
);
1047 generator
.emitNodeInConditionContext(branchExpression
, falseTarget
, trueTarget
, invert(fallThroughMode
));
1050 static inline bool canFoldToBranch(OpcodeID opcodeID
, ExpressionNode
* branchExpression
, JSValue constant
)
1052 ResultType expressionType
= branchExpression
->resultDescriptor();
1054 if (expressionType
.definitelyIsBoolean() && constant
.isBoolean())
1056 else if (expressionType
.definitelyIsBoolean() && constant
.isInt32() && (constant
.asInt32() == 0 || constant
.asInt32() == 1))
1057 return opcodeID
== op_eq
|| opcodeID
== op_neq
; // Strict equality is false in the case of type mismatch.
1058 else if (expressionType
.isInt32() && constant
.isInt32() && constant
.asInt32() == 0)
1064 void BinaryOpNode::tryFoldToBranch(BytecodeGenerator
& generator
, TriState
& branchCondition
, ExpressionNode
*& branchExpression
)
1066 branchCondition
= MixedTriState
;
1067 branchExpression
= 0;
1069 ConstantNode
* constant
= 0;
1070 if (m_expr1
->isConstant()) {
1071 constant
= static_cast<ConstantNode
*>(m_expr1
);
1072 branchExpression
= m_expr2
;
1073 } else if (m_expr2
->isConstant()) {
1074 constant
= static_cast<ConstantNode
*>(m_expr2
);
1075 branchExpression
= m_expr1
;
1080 ASSERT(branchExpression
);
1082 OpcodeID opcodeID
= this->opcodeID();
1083 JSValue value
= constant
->jsValue(generator
);
1084 bool canFoldToBranch
= JSC::canFoldToBranch(opcodeID
, branchExpression
, value
);
1085 if (!canFoldToBranch
)
1088 if (opcodeID
== op_eq
|| opcodeID
== op_stricteq
)
1089 branchCondition
= triState(value
.pureToBoolean());
1090 else if (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
)
1091 branchCondition
= triState(!value
.pureToBoolean());
1094 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1096 OpcodeID opcodeID
= this->opcodeID();
1098 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString())
1099 return emitStrcat(generator
, dst
);
1101 if (opcodeID
== op_neq
) {
1102 if (m_expr1
->isNull() || m_expr2
->isNull()) {
1103 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
1104 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
1105 return generator
.emitUnaryOp(op_neq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
1109 ExpressionNode
* left
= m_expr1
;
1110 ExpressionNode
* right
= m_expr2
;
1111 if (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
) {
1112 if (left
->isString())
1113 std::swap(left
, right
);
1116 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, right
->isPure(generator
));
1117 bool wasTypeof
= generator
.m_lastOpcodeID
== op_typeof
;
1118 RegisterID
* src2
= generator
.emitNode(right
);
1119 if (wasTypeof
&& (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
)) {
1120 RefPtr
<RegisterID
> tmp
= generator
.tempDestination(dst
);
1121 if (opcodeID
== op_neq
)
1122 generator
.emitEqualityOp(op_eq
, generator
.finalDestination(tmp
.get(), src1
.get()), src1
.get(), src2
);
1123 else if (opcodeID
== op_nstricteq
)
1124 generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(tmp
.get(), src1
.get()), src1
.get(), src2
);
1126 RELEASE_ASSERT_NOT_REACHED();
1127 return generator
.emitUnaryOp(op_not
, generator
.finalDestination(dst
, tmp
.get()), tmp
.get());
1129 return generator
.emitBinaryOp(opcodeID
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(left
->resultDescriptor(), right
->resultDescriptor()));
1132 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1134 if (m_expr1
->isNull() || m_expr2
->isNull()) {
1135 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
1136 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
1137 return generator
.emitUnaryOp(op_eq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
1140 ExpressionNode
* left
= m_expr1
;
1141 ExpressionNode
* right
= m_expr2
;
1142 if (left
->isString())
1143 std::swap(left
, right
);
1145 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1146 RegisterID
* src2
= generator
.emitNode(right
);
1147 return generator
.emitEqualityOp(op_eq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
1150 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1152 ExpressionNode
* left
= m_expr1
;
1153 ExpressionNode
* right
= m_expr2
;
1154 if (left
->isString())
1155 std::swap(left
, right
);
1157 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1158 RegisterID
* src2
= generator
.emitNode(right
);
1159 return generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
1162 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1164 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1165 RegisterID
* src2
= generator
.emitNode(m_expr2
);
1166 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1167 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
1170 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1172 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1173 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
1174 RefPtr
<RegisterID
> prototype
= generator
.newTemporary();
1175 RefPtr
<RegisterID
> dstReg
= generator
.finalDestination(dst
, src1
.get());
1176 RefPtr
<Label
> target
= generator
.newLabel();
1178 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1179 generator
.emitCheckHasInstance(dstReg
.get(), src1
.get(), src2
.get(), target
.get());
1181 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1182 generator
.emitGetById(prototype
.get(), src2
.get(), generator
.vm()->propertyNames
->prototype
);
1184 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1185 RegisterID
* result
= generator
.emitInstanceOf(dstReg
.get(), src1
.get(), prototype
.get());
1186 generator
.emitLabel(target
.get());
1190 // ------------------------------ LogicalOpNode ----------------------------
1192 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1194 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
1195 RefPtr
<Label
> target
= generator
.newLabel();
1197 generator
.emitNode(temp
.get(), m_expr1
);
1198 if (m_operator
== OpLogicalAnd
)
1199 generator
.emitJumpIfFalse(temp
.get(), target
.get());
1201 generator
.emitJumpIfTrue(temp
.get(), target
.get());
1202 generator
.emitNode(temp
.get(), m_expr2
);
1203 generator
.emitLabel(target
.get());
1205 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
1208 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1210 RefPtr
<Label
> afterExpr1
= generator
.newLabel();
1211 if (m_operator
== OpLogicalAnd
)
1212 generator
.emitNodeInConditionContext(m_expr1
, afterExpr1
.get(), falseTarget
, FallThroughMeansTrue
);
1214 generator
.emitNodeInConditionContext(m_expr1
, trueTarget
, afterExpr1
.get(), FallThroughMeansFalse
);
1215 generator
.emitLabel(afterExpr1
.get());
1217 generator
.emitNodeInConditionContext(m_expr2
, trueTarget
, falseTarget
, fallThroughMode
);
1220 // ------------------------------ ConditionalNode ------------------------------
1222 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1224 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
1225 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1226 RefPtr
<Label
> afterElse
= generator
.newLabel();
1228 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1229 generator
.emitNodeInConditionContext(m_logical
, beforeThen
.get(), beforeElse
.get(), FallThroughMeansTrue
);
1230 generator
.emitLabel(beforeThen
.get());
1232 generator
.emitNode(newDst
.get(), m_expr1
);
1233 generator
.emitJump(afterElse
.get());
1235 generator
.emitLabel(beforeElse
.get());
1236 generator
.emitNode(newDst
.get(), m_expr2
);
1238 generator
.emitLabel(afterElse
.get());
1240 return newDst
.get();
1243 // ------------------------------ ReadModifyResolveNode -----------------------------------
1245 // FIXME: should this be moved to be a method on BytecodeGenerator?
1246 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1257 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1258 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1265 opcodeID
= op_lshift
;
1268 opcodeID
= op_rshift
;
1271 opcodeID
= op_urshift
;
1274 opcodeID
= op_bitand
;
1277 opcodeID
= op_bitxor
;
1280 opcodeID
= op_bitor
;
1286 RELEASE_ASSERT_NOT_REACHED();
1290 RegisterID
* src2
= generator
.emitNode(m_right
);
1292 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1293 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1294 if (emitExpressionInfoForMe
)
1295 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->divotStartOffset(), emitExpressionInfoForMe
->divotEndOffset(), emitExpressionInfoForMe
->divotLine(), emitExpressionInfoForMe
->divotLineStart());
1297 return generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1300 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1302 ResolveResult resolveResult
= generator
.resolve(m_ident
);
1304 if (RegisterID
*local
= resolveResult
.local()) {
1305 if (resolveResult
.isReadOnly()) {
1306 generator
.emitReadOnlyExceptionIfNeeded();
1307 return emitReadModifyAssignment(generator
, generator
.finalDestination(dst
), local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1310 if (generator
.leftHandSideNeedsCopy(m_rightHasAssignments
, m_right
->isPure(generator
))) {
1311 RefPtr
<RegisterID
> result
= generator
.newTemporary();
1312 generator
.emitMove(result
.get(), local
);
1313 emitReadModifyAssignment(generator
, result
.get(), result
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1314 generator
.emitMove(local
, result
.get());
1315 return generator
.moveToDestinationIfNeeded(dst
, result
.get());
1318 RegisterID
* result
= emitReadModifyAssignment(generator
, local
, local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1319 return generator
.moveToDestinationIfNeeded(dst
, result
);
1322 if (resolveResult
.isStatic() && !resolveResult
.isReadOnly()) {
1323 RefPtr
<RegisterID
> src1
= generator
.emitGetStaticVar(generator
.tempDestination(dst
), resolveResult
, m_ident
);
1324 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1325 generator
.emitPutStaticVar(resolveResult
, m_ident
, result
);
1329 RefPtr
<RegisterID
> src1
= generator
.tempDestination(dst
);
1330 generator
.emitExpressionInfo(divot() - divotStartOffset() + m_ident
.length(), m_ident
.length(), 0, divotLine(), divotLineStart());
1331 NonlocalResolveInfo resolveVerifier
;
1332 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBaseForPut(generator
.newTemporary(), src1
.get(), resolveResult
, m_ident
, resolveVerifier
);
1333 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()), this);
1334 return generator
.emitPutToBase(base
.get(), m_ident
, result
, resolveVerifier
);
1337 // ------------------------------ AssignResolveNode -----------------------------------
1339 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1341 ResolveResult resolveResult
= generator
.resolve(m_ident
);
1343 if (RegisterID
* local
= resolveResult
.local()) {
1344 if (resolveResult
.isReadOnly()) {
1345 generator
.emitReadOnlyExceptionIfNeeded();
1346 return generator
.emitNode(dst
, m_right
);
1348 RegisterID
* result
= generator
.emitNode(local
, m_right
);
1349 return generator
.moveToDestinationIfNeeded(dst
, result
);
1352 if (resolveResult
.isStatic() && !resolveResult
.isReadOnly()) {
1353 if (dst
== generator
.ignoredResult())
1355 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1356 generator
.emitPutStaticVar(resolveResult
, m_ident
, value
);
1360 NonlocalResolveInfo resolveVerifier
;
1361 RefPtr
<RegisterID
> base
= generator
.emitResolveBaseForPut(generator
.newTemporary(), resolveResult
, m_ident
, resolveVerifier
);
1362 if (dst
== generator
.ignoredResult())
1364 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1365 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1366 return generator
.emitPutToBase(base
.get(), m_ident
, value
, resolveVerifier
);
1369 // ------------------------------ AssignDotNode -----------------------------------
1371 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1373 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1374 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1375 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1376 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1377 RegisterID
* forwardResult
= (dst
== generator
.ignoredResult()) ? result
: generator
.moveToDestinationIfNeeded(generator
.tempDestination(result
), result
);
1378 generator
.emitPutById(base
.get(), m_ident
, forwardResult
);
1379 return generator
.moveToDestinationIfNeeded(dst
, forwardResult
);
1382 // ------------------------------ ReadModifyDotNode -----------------------------------
1384 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1386 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1388 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
1389 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
1390 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1392 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1393 return generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1396 // ------------------------------ AssignErrorNode -----------------------------------
1398 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1400 return emitThrowReferenceError(generator
, "Left side of assignment is not a reference.");
1403 // ------------------------------ AssignBracketNode -----------------------------------
1405 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1407 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1408 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1409 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1410 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1412 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1413 RegisterID
* forwardResult
= (dst
== generator
.ignoredResult()) ? result
: generator
.moveToDestinationIfNeeded(generator
.tempDestination(result
), result
);
1414 generator
.emitPutByVal(base
.get(), property
.get(), forwardResult
);
1415 return generator
.moveToDestinationIfNeeded(dst
, forwardResult
);
1418 // ------------------------------ ReadModifyBracketNode -----------------------------------
1420 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1422 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1423 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1425 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStartOffset(), subexpressionEndOffset(), subexpressionLine(), subexpressionLineStart());
1426 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
1427 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1429 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1430 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1432 return updatedValue
;
1435 // ------------------------------ CommaNode ------------------------------------
1437 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1439 ASSERT(m_expressions
.size() > 1);
1440 for (size_t i
= 0; i
< m_expressions
.size() - 1; i
++)
1441 generator
.emitNode(generator
.ignoredResult(), m_expressions
[i
]);
1442 return generator
.emitNode(dst
, m_expressions
.last());
1445 // ------------------------------ ConstDeclNode ------------------------------------
1447 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1449 ResolveResult resolveResult
= generator
.resolveConstDecl(m_ident
);
1451 // FIXME: This code does not match the behavior of const in Firefox.
1452 if (RegisterID
* local
= resolveResult
.local()) {
1456 return generator
.emitNode(local
, m_init
);
1459 RefPtr
<RegisterID
> value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1461 if (generator
.codeType() == GlobalCode
)
1462 return generator
.emitInitGlobalConst(m_ident
, value
.get());
1464 if (generator
.codeType() != EvalCode
)
1467 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
1468 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), resolveResult
, m_ident
);
1469 return generator
.emitPutById(base
.get(), m_ident
, value
.get());
1472 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1474 RegisterID
* result
= 0;
1475 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1476 result
= n
->emitCodeSingle(generator
);
1481 // ------------------------------ ConstStatementNode -----------------------------
1483 void ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1485 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1486 generator
.emitNode(m_next
);
1489 // ------------------------------ SourceElements -------------------------------
1492 inline StatementNode
* SourceElements::lastStatement() const
1494 size_t size
= m_statements
.size();
1495 return size
? m_statements
[size
- 1] : 0;
1498 inline void SourceElements::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1500 size_t size
= m_statements
.size();
1501 for (size_t i
= 0; i
< size
; ++i
)
1502 generator
.emitNode(dst
, m_statements
[i
]);
1505 // ------------------------------ BlockNode ------------------------------------
1507 inline StatementNode
* BlockNode::lastStatement() const
1509 return m_statements
? m_statements
->lastStatement() : 0;
1512 inline StatementNode
* BlockNode::singleStatement() const
1514 return m_statements
? m_statements
->singleStatement() : 0;
1517 void BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1521 m_statements
->emitBytecode(generator
, dst
);
1524 // ------------------------------ EmptyStatementNode ---------------------------
1526 void EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1528 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1531 // ------------------------------ DebuggerStatementNode ---------------------------
1533 void DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1535 generator
.emitDebugHook(DidReachBreakpoint
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1538 // ------------------------------ ExprStatementNode ----------------------------
1540 void ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1543 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1544 generator
.emitNode(dst
, m_expr
);
1547 // ------------------------------ VarStatementNode ----------------------------
1549 void VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1552 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1553 generator
.emitNode(m_expr
);
1556 // ------------------------------ IfElseNode ---------------------------------------
1558 static inline StatementNode
* singleStatement(StatementNode
* statementNode
)
1560 if (statementNode
->isBlock())
1561 return static_cast<BlockNode
*>(statementNode
)->singleStatement();
1562 return statementNode
;
1565 bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator
& generator
, StatementNode
* ifBlock
,
1566 Label
*& trueTarget
, FallThroughMode
& fallThroughMode
)
1568 StatementNode
* singleStatement
= JSC::singleStatement(ifBlock
);
1569 if (!singleStatement
)
1572 if (singleStatement
->isBreak()) {
1573 BreakNode
* breakNode
= static_cast<BreakNode
*>(singleStatement
);
1574 Label
* target
= breakNode
->trivialTarget(generator
);
1577 trueTarget
= target
;
1578 fallThroughMode
= FallThroughMeansFalse
;
1582 if (singleStatement
->isContinue()) {
1583 ContinueNode
* continueNode
= static_cast<ContinueNode
*>(singleStatement
);
1584 Label
* target
= continueNode
->trivialTarget(generator
);
1587 trueTarget
= target
;
1588 fallThroughMode
= FallThroughMeansFalse
;
1595 void IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1597 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1599 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1600 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1601 RefPtr
<Label
> afterElse
= generator
.newLabel();
1603 Label
* trueTarget
= beforeThen
.get();
1604 Label
* falseTarget
= beforeElse
.get();
1605 FallThroughMode fallThroughMode
= FallThroughMeansTrue
;
1606 bool didFoldIfBlock
= tryFoldBreakAndContinue(generator
, m_ifBlock
, trueTarget
, fallThroughMode
);
1608 generator
.emitNodeInConditionContext(m_condition
, trueTarget
, falseTarget
, fallThroughMode
);
1609 generator
.emitLabel(beforeThen
.get());
1611 if (!didFoldIfBlock
) {
1612 generator
.emitNode(dst
, m_ifBlock
);
1614 generator
.emitJump(afterElse
.get());
1617 generator
.emitLabel(beforeElse
.get());
1620 generator
.emitNode(dst
, m_elseBlock
);
1622 generator
.emitLabel(afterElse
.get());
1625 // ------------------------------ DoWhileNode ----------------------------------
1627 void DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1629 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1631 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1632 generator
.emitLabel(topOfLoop
.get());
1633 generator
.emitLoopHint();
1634 generator
.emitDebugHook(WillExecuteStatement
, lastLine(), lastLine(), startOffset(), lineStartOffset());
1636 generator
.emitNode(dst
, m_statement
);
1638 generator
.emitLabel(scope
->continueTarget());
1639 generator
.emitDebugHook(WillExecuteStatement
, lastLine(), lastLine(), startOffset(), lineStartOffset());
1640 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
1642 generator
.emitLabel(scope
->breakTarget());
1645 // ------------------------------ WhileNode ------------------------------------
1647 void WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1649 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1650 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1652 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo(), m_expr
->startOffset(), m_expr
->lineStartOffset());
1653 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansTrue
);
1655 generator
.emitLabel(topOfLoop
.get());
1656 generator
.emitLoopHint();
1658 generator
.emitNode(dst
, m_statement
);
1660 generator
.emitLabel(scope
->continueTarget());
1661 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1663 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
1665 generator
.emitLabel(scope
->breakTarget());
1668 // ------------------------------ ForNode --------------------------------------
1670 void ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1672 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1674 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1677 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
1679 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1681 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansTrue
);
1683 generator
.emitLabel(topOfLoop
.get());
1684 generator
.emitLoopHint();
1686 generator
.emitNode(dst
, m_statement
);
1688 generator
.emitLabel(scope
->continueTarget());
1689 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1691 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
1694 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
1696 generator
.emitJump(topOfLoop
.get());
1698 generator
.emitLabel(scope
->breakTarget());
1701 // ------------------------------ ForInNode ------------------------------------
1703 void ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1705 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1707 if (!m_lexpr
->isLocation()) {
1708 emitThrowReferenceError(generator
, "Left side of for-in statement is not a reference.");
1712 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1715 generator
.emitNode(generator
.ignoredResult(), m_init
);
1717 RefPtr
<RegisterID
> base
= generator
.newTemporary();
1718 generator
.emitNode(base
.get(), m_expr
);
1719 RefPtr
<RegisterID
> i
= generator
.newTemporary();
1720 RefPtr
<RegisterID
> size
= generator
.newTemporary();
1721 RefPtr
<RegisterID
> expectedSubscript
;
1722 RefPtr
<RegisterID
> iter
= generator
.emitGetPropertyNames(generator
.newTemporary(), base
.get(), i
.get(), size
.get(), scope
->breakTarget());
1723 generator
.emitJump(scope
->continueTarget());
1725 RefPtr
<Label
> loopStart
= generator
.newLabel();
1726 generator
.emitLabel(loopStart
.get());
1727 generator
.emitLoopHint();
1729 RegisterID
* propertyName
;
1730 bool optimizedForinAccess
= false;
1731 if (m_lexpr
->isResolveNode()) {
1732 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1733 ResolveResult resolveResult
= generator
.resolve(ident
);
1734 propertyName
= resolveResult
.local();
1735 if (!propertyName
) {
1736 propertyName
= generator
.newTemporary();
1737 RefPtr
<RegisterID
> protect
= propertyName
;
1738 NonlocalResolveInfo resolveVerifier
;
1739 RegisterID
* base
= generator
.emitResolveBaseForPut(generator
.newTemporary(), resolveResult
, ident
, resolveVerifier
);
1741 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
1742 generator
.emitPutToBase(base
, ident
, propertyName
, resolveVerifier
);
1744 expectedSubscript
= generator
.emitMove(generator
.newTemporary(), propertyName
);
1745 generator
.pushOptimisedForIn(expectedSubscript
.get(), iter
.get(), i
.get(), propertyName
);
1746 optimizedForinAccess
= true;
1748 } else if (m_lexpr
->isDotAccessorNode()) {
1749 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1750 const Identifier
& ident
= assignNode
->identifier();
1751 propertyName
= generator
.newTemporary();
1752 RefPtr
<RegisterID
> protect
= propertyName
;
1753 RegisterID
* base
= generator
.emitNode(assignNode
->base());
1755 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStartOffset(), assignNode
->divotEndOffset(), assignNode
->divotLine(), assignNode
->divotLineStart());
1756 generator
.emitPutById(base
, ident
, propertyName
);
1758 ASSERT(m_lexpr
->isBracketAccessorNode());
1759 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1760 propertyName
= generator
.newTemporary();
1761 RefPtr
<RegisterID
> protect
= propertyName
;
1762 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1763 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1765 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStartOffset(), assignNode
->divotEndOffset(), assignNode
->divotLine(), assignNode
->divotLineStart());
1766 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
1769 generator
.emitNode(dst
, m_statement
);
1771 if (optimizedForinAccess
)
1772 generator
.popOptimisedForIn();
1774 generator
.emitLabel(scope
->continueTarget());
1775 generator
.emitNextPropertyName(propertyName
, base
.get(), i
.get(), size
.get(), iter
.get(), loopStart
.get());
1776 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1777 generator
.emitLabel(scope
->breakTarget());
1780 // ------------------------------ ContinueNode ---------------------------------
1782 Label
* ContinueNode::trivialTarget(BytecodeGenerator
& generator
)
1784 if (generator
.shouldEmitDebugHooks())
1787 LabelScope
* scope
= generator
.continueTarget(m_ident
);
1790 if (generator
.scopeDepth() != scope
->scopeDepth())
1793 return scope
->continueTarget();
1796 void ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1798 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1800 LabelScope
* scope
= generator
.continueTarget(m_ident
);
1803 generator
.emitPopScopes(scope
->scopeDepth());
1804 generator
.emitJump(scope
->continueTarget());
1807 // ------------------------------ BreakNode ------------------------------------
1809 Label
* BreakNode::trivialTarget(BytecodeGenerator
& generator
)
1811 if (generator
.shouldEmitDebugHooks())
1814 LabelScope
* scope
= generator
.breakTarget(m_ident
);
1817 if (generator
.scopeDepth() != scope
->scopeDepth())
1820 return scope
->breakTarget();
1823 void BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1825 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1827 LabelScope
* scope
= generator
.breakTarget(m_ident
);
1830 generator
.emitPopScopes(scope
->scopeDepth());
1831 generator
.emitJump(scope
->breakTarget());
1834 // ------------------------------ ReturnNode -----------------------------------
1836 void ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1838 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1839 ASSERT(generator
.codeType() == FunctionCode
);
1841 if (dst
== generator
.ignoredResult())
1844 RefPtr
<RegisterID
> returnRegister
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
1845 if (generator
.scopeDepth()) {
1846 returnRegister
= generator
.emitMove(generator
.newTemporary(), returnRegister
.get());
1847 generator
.emitPopScopes(0);
1850 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1851 generator
.emitReturn(returnRegister
.get());
1854 // ------------------------------ WithNode -------------------------------------
1856 void WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1858 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
1860 RefPtr
<RegisterID
> scope
= generator
.emitNode(m_expr
);
1861 generator
.emitExpressionInfo(m_divot
, m_expressionLength
, 0, m_divotLine
, m_divotLineStart
);
1862 generator
.emitPushWithScope(scope
.get());
1863 generator
.emitNode(dst
, m_statement
);
1864 generator
.emitPopScope();
1867 // ------------------------------ CaseClauseNode --------------------------------
1869 inline void CaseClauseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1873 m_statements
->emitBytecode(generator
, dst
);
1876 // ------------------------------ CaseBlockNode --------------------------------
1885 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
1887 for (; list
; list
= list
->getNext()) {
1888 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
1889 literalVector
.append(clauseExpression
);
1890 if (clauseExpression
->isNumber()) {
1891 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
1892 int32_t intVal
= static_cast<int32_t>(value
);
1893 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
1894 typeForTable
= SwitchNeither
;
1897 if (intVal
< min_num
)
1899 if (intVal
> max_num
)
1901 typeForTable
= SwitchNumber
;
1904 if (clauseExpression
->isString()) {
1905 if (typeForTable
& ~SwitchString
) {
1906 typeForTable
= SwitchNeither
;
1909 const String
& value
= static_cast<StringNode
*>(clauseExpression
)->value().string();
1910 if (singleCharacterSwitch
&= value
.length() == 1) {
1911 int32_t intVal
= value
[0];
1912 if (intVal
< min_num
)
1914 if (intVal
> max_num
)
1917 typeForTable
= SwitchString
;
1920 typeForTable
= SwitchNeither
;
1925 static inline size_t length(ClauseListNode
* list1
, ClauseListNode
* list2
)
1928 for (ClauseListNode
* node
= list1
; node
; node
= node
->getNext())
1930 for (ClauseListNode
* node
= list2
; node
; node
= node
->getNext())
1935 SwitchInfo::SwitchType
CaseBlockNode::tryTableSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
1937 if (length(m_list1
, m_list2
) < s_tableSwitchMinimum
)
1938 return SwitchInfo::SwitchNone
;
1940 SwitchKind typeForTable
= SwitchUnset
;
1941 bool singleCharacterSwitch
= true;
1943 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1944 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1946 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
1947 return SwitchInfo::SwitchNone
;
1949 if (typeForTable
== SwitchNumber
) {
1950 int32_t range
= max_num
- min_num
;
1951 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1952 return SwitchInfo::SwitchImmediate
;
1953 return SwitchInfo::SwitchNone
;
1956 ASSERT(typeForTable
== SwitchString
);
1958 if (singleCharacterSwitch
) {
1959 int32_t range
= max_num
- min_num
;
1960 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1961 return SwitchInfo::SwitchCharacter
;
1964 return SwitchInfo::SwitchString
;
1967 void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
1969 RefPtr
<Label
> defaultLabel
;
1970 Vector
<RefPtr
<Label
>, 8> labelVector
;
1971 Vector
<ExpressionNode
*, 8> literalVector
;
1972 int32_t min_num
= std::numeric_limits
<int32_t>::max();
1973 int32_t max_num
= std::numeric_limits
<int32_t>::min();
1974 SwitchInfo::SwitchType switchType
= tryTableSwitch(literalVector
, min_num
, max_num
);
1976 if (switchType
!= SwitchInfo::SwitchNone
) {
1977 // Prepare the various labels
1978 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
1979 labelVector
.append(generator
.newLabel());
1980 defaultLabel
= generator
.newLabel();
1981 generator
.beginSwitch(switchExpression
, switchType
);
1984 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1985 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1986 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1987 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1988 labelVector
.append(generator
.newLabel());
1989 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1992 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1993 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1994 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1995 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1996 labelVector
.append(generator
.newLabel());
1997 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1999 defaultLabel
= generator
.newLabel();
2000 generator
.emitJump(defaultLabel
.get());
2004 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
2005 generator
.emitLabel(labelVector
[i
++].get());
2006 list
->getClause()->emitBytecode(generator
, dst
);
2009 if (m_defaultClause
) {
2010 generator
.emitLabel(defaultLabel
.get());
2011 m_defaultClause
->emitBytecode(generator
, dst
);
2014 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
2015 generator
.emitLabel(labelVector
[i
++].get());
2016 list
->getClause()->emitBytecode(generator
, dst
);
2018 if (!m_defaultClause
)
2019 generator
.emitLabel(defaultLabel
.get());
2021 ASSERT(i
== labelVector
.size());
2022 if (switchType
!= SwitchInfo::SwitchNone
) {
2023 ASSERT(labelVector
.size() == literalVector
.size());
2024 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
2028 // ------------------------------ SwitchNode -----------------------------------
2030 void SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2032 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
2034 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Switch
);
2036 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
2037 m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
2039 generator
.emitLabel(scope
->breakTarget());
2042 // ------------------------------ LabelNode ------------------------------------
2044 void LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2046 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
2048 ASSERT(!generator
.breakTarget(m_name
));
2050 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
2051 generator
.emitNode(dst
, m_statement
);
2053 generator
.emitLabel(scope
->breakTarget());
2056 // ------------------------------ ThrowNode ------------------------------------
2058 void ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2060 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
2062 if (dst
== generator
.ignoredResult())
2064 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
2065 generator
.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());
2066 generator
.emitThrow(expr
.get());
2069 // ------------------------------ TryNode --------------------------------------
2071 void TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2073 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2074 // optimizer knows they may be jumped to from anywhere.
2076 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine(), startOffset(), lineStartOffset());
2078 ASSERT(m_catchBlock
|| m_finallyBlock
);
2080 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
2081 generator
.emitLabel(tryStartLabel
.get());
2084 generator
.pushFinallyContext(m_finallyBlock
);
2085 TryData
* tryData
= generator
.pushTry(tryStartLabel
.get());
2087 generator
.emitNode(dst
, m_tryBlock
);
2090 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
2092 // Normal path: jump over the catch block.
2093 generator
.emitJump(catchEndLabel
.get());
2095 // Uncaught exception path: the catch block.
2096 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
2097 RefPtr
<RegisterID
> exceptionRegister
= generator
.popTryAndEmitCatch(tryData
, generator
.newTemporary(), here
.get());
2099 if (m_finallyBlock
) {
2100 // If the catch block throws an exception and we have a finally block, then the finally
2101 // block should "catch" that exception.
2102 tryData
= generator
.pushTry(here
.get());
2105 generator
.emitPushNameScope(m_exceptionIdent
, exceptionRegister
.get(), DontDelete
);
2106 generator
.emitNode(dst
, m_catchBlock
);
2107 generator
.emitPopScope();
2108 generator
.emitLabel(catchEndLabel
.get());
2111 if (m_finallyBlock
) {
2112 RefPtr
<Label
> preFinallyLabel
= generator
.emitLabel(generator
.newLabel().get());
2114 generator
.popFinallyContext();
2116 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
2118 // Normal path: run the finally code, and jump to the end.
2119 generator
.emitNode(dst
, m_finallyBlock
);
2120 generator
.emitJump(finallyEndLabel
.get());
2122 // Uncaught exception path: invoke the finally block, then re-throw the exception.
2123 RefPtr
<RegisterID
> tempExceptionRegister
= generator
.popTryAndEmitCatch(tryData
, generator
.newTemporary(), preFinallyLabel
.get());
2124 generator
.emitNode(dst
, m_finallyBlock
);
2125 generator
.emitThrow(tempExceptionRegister
.get());
2127 generator
.emitLabel(finallyEndLabel
.get());
2131 // ------------------------------ ScopeNode -----------------------------
2133 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2137 m_statements
->emitBytecode(generator
, dst
);
2140 // ------------------------------ ProgramNode -----------------------------
2142 void ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2144 generator
.emitDebugHook(WillExecuteProgram
, startLine(), startLine(), startStartOffset(), startLineStartOffset());
2146 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
2147 generator
.emitLoad(dstRegister
.get(), jsUndefined());
2148 emitStatementsBytecode(generator
, dstRegister
.get());
2150 generator
.emitDebugHook(DidExecuteProgram
, lastLine(), lastLine(), startOffset(), lineStartOffset());
2151 generator
.emitEnd(dstRegister
.get());
2154 // ------------------------------ EvalNode -----------------------------
2156 void EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2158 generator
.emitDebugHook(WillExecuteProgram
, startLine(), startLine(), startStartOffset(), startLineStartOffset());
2160 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
2161 generator
.emitLoad(dstRegister
.get(), jsUndefined());
2162 emitStatementsBytecode(generator
, dstRegister
.get());
2164 generator
.emitDebugHook(DidExecuteProgram
, lastLine(), lastLine(), startOffset(), lineStartOffset());
2165 generator
.emitEnd(dstRegister
.get());
2168 // ------------------------------ FunctionBodyNode -----------------------------
2170 void FunctionBodyNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2172 generator
.emitDebugHook(DidEnterCallFrame
, startLine(), startLine(), startStartOffset(), startLineStartOffset());
2173 emitStatementsBytecode(generator
, generator
.ignoredResult());
2175 StatementNode
* singleStatement
= this->singleStatement();
2176 ReturnNode
* returnNode
= 0;
2178 // Check for a return statement at the end of a function composed of a single block.
2179 if (singleStatement
&& singleStatement
->isBlock()) {
2180 StatementNode
* lastStatementInBlock
= static_cast<BlockNode
*>(singleStatement
)->lastStatement();
2181 if (lastStatementInBlock
&& lastStatementInBlock
->isReturnNode())
2182 returnNode
= static_cast<ReturnNode
*>(lastStatementInBlock
);
2185 // If there is no return we must automatically insert one.
2187 RegisterID
* r0
= generator
.isConstructor() ? generator
.thisRegister() : generator
.emitLoad(0, jsUndefined());
2188 ASSERT((startOffset() - 1) >= lineStartOffset());
2189 generator
.emitDebugHook(WillLeaveCallFrame
, lastLine(), lastLine(), startOffset() - 1, lineStartOffset());
2190 generator
.emitReturn(r0
);
2194 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
2195 if (static_cast<BlockNode
*>(singleStatement
)->singleStatement()) {
2196 ExpressionNode
* returnValueExpression
= returnNode
->value();
2197 if (returnValueExpression
&& returnValueExpression
->isSubtract()) {
2198 ExpressionNode
* lhsExpression
= static_cast<SubNode
*>(returnValueExpression
)->lhs();
2199 ExpressionNode
* rhsExpression
= static_cast<SubNode
*>(returnValueExpression
)->rhs();
2200 if (lhsExpression
->isResolveNode()
2201 && rhsExpression
->isResolveNode()
2202 && generator
.isArgumentNumber(static_cast<ResolveNode
*>(lhsExpression
)->identifier(), 0)
2203 && generator
.isArgumentNumber(static_cast<ResolveNode
*>(rhsExpression
)->identifier(), 1)) {
2205 generator
.setIsNumericCompareFunction(true);
2211 // ------------------------------ FuncDeclNode ---------------------------------
2213 void FuncDeclNode::emitBytecode(BytecodeGenerator
&, RegisterID
*)
2217 // ------------------------------ FuncExprNode ---------------------------------
2219 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2221 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);