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 "BuiltinNames.h"
32 #include "BytecodeGenerator.h"
33 #include "CallFrame.h"
36 #include "JSFunction.h"
37 #include "JSGlobalObject.h"
38 #include "JSNameScope.h"
39 #include "JSONObject.h"
40 #include "LabelScope.h"
42 #include "JSCInlines.h"
44 #include "PropertyNameArray.h"
45 #include "RegExpCache.h"
46 #include "RegExpObject.h"
47 #include "SamplingTool.h"
48 #include "StackAlignment.h"
49 #include <wtf/Assertions.h>
50 #include <wtf/RefCountedLeakCounter.h>
51 #include <wtf/Threading.h>
58 Details of the emitBytecode function.
60 Return value: The register holding the production's value.
61 dst: An optional parameter specifying the most efficient destination at
62 which to store the production's value. The callee must honor dst.
64 The dst argument provides for a crude form of copy propagation. For example,
77 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
80 void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
82 RegisterID
* result
= generator
.emitNode(this);
83 if (fallThroughMode
== FallThroughMeansTrue
)
84 generator
.emitJumpIfFalse(result
, falseTarget
);
86 generator
.emitJumpIfTrue(result
, trueTarget
);
89 // ------------------------------ ThrowableExpressionData --------------------------------
91 RegisterID
* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator
& generator
, const String
& message
)
93 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
94 generator
.emitThrowReferenceError(message
);
95 return generator
.newTemporary();
98 // ------------------------------ ConstantNode ----------------------------------
100 void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
102 TriState value
= jsValue(generator
).pureToBoolean();
103 if (value
== MixedTriState
)
104 ExpressionNode::emitBytecodeInConditionContext(generator
, trueTarget
, falseTarget
, fallThroughMode
);
105 else if (value
== TrueTriState
&& fallThroughMode
== FallThroughMeansFalse
)
106 generator
.emitJump(trueTarget
);
107 else if (value
== FalseTriState
&& fallThroughMode
== FallThroughMeansTrue
)
108 generator
.emitJump(falseTarget
);
110 // All other cases are unconditional fall-throughs, like "if (true)".
113 RegisterID
* ConstantNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
115 if (dst
== generator
.ignoredResult())
117 return generator
.emitLoad(dst
, jsValue(generator
));
120 JSValue
StringNode::jsValue(BytecodeGenerator
& generator
) const
122 return generator
.addStringConstant(m_value
);
125 // ------------------------------ RegExpNode -----------------------------------
127 RegisterID
* RegExpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
129 if (dst
== generator
.ignoredResult())
131 return generator
.emitNewRegExp(generator
.finalDestination(dst
), RegExp::create(*generator
.vm(), m_pattern
.string(), regExpFlags(m_flags
.string())));
134 // ------------------------------ ThisNode -------------------------------------
136 RegisterID
* ThisNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
138 if (dst
== generator
.ignoredResult())
140 return generator
.moveToDestinationIfNeeded(dst
, generator
.thisRegister());
143 // ------------------------------ ResolveNode ----------------------------------
145 bool ResolveNode::isPure(BytecodeGenerator
& generator
) const
147 return generator
.local(m_ident
).get();
150 RegisterID
* ResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
152 if (Local local
= generator
.local(m_ident
)) {
153 if (dst
== generator
.ignoredResult())
155 return generator
.moveToDestinationIfNeeded(dst
, local
.get());
158 JSTextPosition divot
= m_start
+ m_ident
.length();
159 generator
.emitExpressionInfo(divot
, m_start
, divot
);
160 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.tempDestination(dst
), m_ident
);
161 return generator
.emitGetFromScope(generator
.finalDestination(dst
), scope
.get(), m_ident
, ThrowIfNotFound
);
164 // ------------------------------ ArrayNode ------------------------------------
166 RegisterID
* ArrayNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
168 // FIXME: Should we put all of this code into emitNewArray?
171 ElementNode
* firstPutElement
;
172 for (firstPutElement
= m_element
; firstPutElement
; firstPutElement
= firstPutElement
->next()) {
173 if (firstPutElement
->elision() || firstPutElement
->value()->isSpreadExpression())
178 if (!firstPutElement
&& !m_elision
)
179 return generator
.emitNewArray(generator
.finalDestination(dst
), m_element
, length
);
181 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.tempDestination(dst
), m_element
, length
);
182 ElementNode
* n
= firstPutElement
;
183 for (; n
; n
= n
->next()) {
184 if (n
->value()->isSpreadExpression())
186 RegisterID
* value
= generator
.emitNode(n
->value());
187 length
+= n
->elision();
188 generator
.emitPutByIndex(array
.get(), length
++, value
);
192 RegisterID
* value
= generator
.emitLoad(0, jsNumber(m_elision
+ length
));
193 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, value
);
196 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
199 RefPtr
<RegisterID
> index
= generator
.emitLoad(generator
.newTemporary(), jsNumber(length
));
200 auto spreader
= [this, array
, index
](BytecodeGenerator
& generator
, RegisterID
* value
)
202 generator
.emitDirectPutByVal(array
.get(), index
.get(), value
);
203 generator
.emitInc(index
.get());
205 for (; n
; n
= n
->next()) {
207 generator
.emitBinaryOp(op_add
, index
.get(), index
.get(), generator
.emitLoad(0, jsNumber(n
->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
208 if (n
->value()->isSpreadExpression()) {
209 SpreadExpressionNode
* spread
= static_cast<SpreadExpressionNode
*>(n
->value());
210 generator
.emitEnumeration(spread
, spread
->expression(), spreader
);
212 generator
.emitDirectPutByVal(array
.get(), index
.get(), generator
.emitNode(n
->value()));
213 generator
.emitInc(index
.get());
218 generator
.emitBinaryOp(op_add
, index
.get(), index
.get(), generator
.emitLoad(0, jsNumber(m_elision
)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
219 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, index
.get());
221 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
224 bool ArrayNode::isSimpleArray() const
226 if (m_elision
|| m_optional
)
228 for (ElementNode
* ptr
= m_element
; ptr
; ptr
= ptr
->next()) {
235 ArgumentListNode
* ArrayNode::toArgumentList(VM
* vm
, int lineNumber
, int startPosition
) const
237 ASSERT(!m_elision
&& !m_optional
);
238 ElementNode
* ptr
= m_element
;
241 JSTokenLocation location
;
242 location
.line
= lineNumber
;
243 location
.startOffset
= startPosition
;
244 ArgumentListNode
* head
= new (vm
) ArgumentListNode(location
, ptr
->value());
245 ArgumentListNode
* tail
= head
;
247 for (; ptr
; ptr
= ptr
->next()) {
248 ASSERT(!ptr
->elision());
249 tail
= new (vm
) ArgumentListNode(location
, tail
, ptr
->value());
254 // ------------------------------ ObjectLiteralNode ----------------------------
256 RegisterID
* ObjectLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
259 if (dst
== generator
.ignoredResult())
261 return generator
.emitNewObject(generator
.finalDestination(dst
));
263 return generator
.emitNode(dst
, m_list
);
266 // ------------------------------ PropertyListNode -----------------------------
268 RegisterID
* PropertyListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
270 RefPtr
<RegisterID
> newObj
= generator
.tempDestination(dst
);
272 generator
.emitNewObject(newObj
.get());
274 // Fast case: this loop just handles regular value properties.
275 PropertyListNode
* p
= this;
276 for (; p
&& p
->m_node
->m_type
== PropertyNode::Constant
; p
= p
->m_next
) {
277 if (p
->m_node
->m_name
) {
278 generator
.emitDirectPutById(newObj
.get(), *p
->m_node
->name(), generator
.emitNode(p
->m_node
->m_assign
));
281 RefPtr
<RegisterID
> propertyName
= generator
.emitNode(p
->m_node
->m_expression
);
282 generator
.emitDirectPutByVal(newObj
.get(), propertyName
.get(), generator
.emitNode(p
->m_node
->m_assign
));
285 // Were there any get/set properties?
287 typedef std::pair
<PropertyNode
*, PropertyNode
*> GetterSetterPair
;
288 typedef HashMap
<StringImpl
*, GetterSetterPair
> GetterSetterMap
;
291 // Build a map, pairing get/set values together.
292 for (PropertyListNode
* q
= p
; q
; q
= q
->m_next
) {
293 PropertyNode
* node
= q
->m_node
;
294 if (node
->m_type
== PropertyNode::Constant
)
297 GetterSetterPair
pair(node
, static_cast<PropertyNode
*>(0));
298 GetterSetterMap::AddResult result
= map
.add(node
->name()->impl(), pair
);
299 if (!result
.isNewEntry
)
300 result
.iterator
->value
.second
= node
;
303 // Iterate over the remaining properties in the list.
304 for (; p
; p
= p
->m_next
) {
305 PropertyNode
* node
= p
->m_node
;
307 // Handle regular values.
308 if (node
->m_type
== PropertyNode::Constant
) {
310 generator
.emitDirectPutById(newObj
.get(), *node
->name(), generator
.emitNode(node
->m_assign
));
313 RefPtr
<RegisterID
> propertyName
= generator
.emitNode(p
->m_node
->m_expression
);
314 generator
.emitDirectPutByVal(newObj
.get(), propertyName
.get(), generator
.emitNode(p
->m_node
->m_assign
));
318 RegisterID
* value
= generator
.emitNode(node
->m_assign
);
320 // This is a get/set property, find its entry in the map.
321 ASSERT(node
->m_type
== PropertyNode::Getter
|| node
->m_type
== PropertyNode::Setter
);
322 GetterSetterMap::iterator it
= map
.find(node
->name()->impl());
323 ASSERT(it
!= map
.end());
324 GetterSetterPair
& pair
= it
->value
;
326 // Was this already generated as a part of its partner?
327 if (pair
.second
== node
)
330 // Generate the paired node now.
331 RefPtr
<RegisterID
> getterReg
;
332 RefPtr
<RegisterID
> setterReg
;
334 if (node
->m_type
== PropertyNode::Getter
) {
337 ASSERT(pair
.second
->m_type
== PropertyNode::Setter
);
338 setterReg
= generator
.emitNode(pair
.second
->m_assign
);
340 setterReg
= generator
.newTemporary();
341 generator
.emitLoad(setterReg
.get(), jsUndefined());
344 ASSERT(node
->m_type
== PropertyNode::Setter
);
347 ASSERT(pair
.second
->m_type
== PropertyNode::Getter
);
348 getterReg
= generator
.emitNode(pair
.second
->m_assign
);
350 getterReg
= generator
.newTemporary();
351 generator
.emitLoad(getterReg
.get(), jsUndefined());
355 generator
.emitPutGetterSetter(newObj
.get(), *node
->name(), getterReg
.get(), setterReg
.get());
359 return generator
.moveToDestinationIfNeeded(dst
, newObj
.get());
362 // ------------------------------ BracketAccessorNode --------------------------------
364 RegisterID
* BracketAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
366 if (m_base
->isResolveNode()
367 && generator
.willResolveToArguments(static_cast<ResolveNode
*>(m_base
)->identifier())
368 && !generator
.symbolTable().slowArguments()) {
369 RegisterID
* property
= generator
.emitNode(m_subscript
);
370 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
371 return generator
.emitGetArgumentByVal(generator
.finalDestination(dst
), generator
.uncheckedRegisterForArguments(), property
);
374 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
, m_subscript
->isPure(generator
));
375 RegisterID
* property
= generator
.emitNode(m_subscript
);
376 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
377 return generator
.emitGetByVal(generator
.finalDestination(dst
), base
.get(), property
);
380 // ------------------------------ DotAccessorNode --------------------------------
382 RegisterID
* DotAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
384 if (m_ident
== generator
.propertyNames().length
) {
385 if (!m_base
->isResolveNode())
386 goto nonArgumentsPath
;
387 ResolveNode
* resolveNode
= static_cast<ResolveNode
*>(m_base
);
388 if (!generator
.willResolveToArguments(resolveNode
->identifier()))
389 goto nonArgumentsPath
;
390 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
391 return generator
.emitGetArgumentsLength(generator
.finalDestination(dst
), generator
.uncheckedRegisterForArguments());
395 RegisterID
* base
= generator
.emitNode(m_base
);
396 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
397 return generator
.emitGetById(generator
.finalDestination(dst
), base
, m_ident
);
400 // ------------------------------ ArgumentListNode -----------------------------
402 RegisterID
* ArgumentListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
405 return generator
.emitNode(dst
, m_expr
);
408 // ------------------------------ NewExprNode ----------------------------------
410 RegisterID
* NewExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
412 ExpectedFunction expectedFunction
;
413 if (m_expr
->isResolveNode())
414 expectedFunction
= generator
.expectedFunctionForIdentifier(static_cast<ResolveNode
*>(m_expr
)->identifier());
416 expectedFunction
= NoExpectedFunction
;
417 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
418 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
419 CallArguments
callArguments(generator
, m_args
);
420 return generator
.emitConstruct(returnValue
.get(), func
.get(), expectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
423 CallArguments::CallArguments(BytecodeGenerator
& generator
, ArgumentsNode
* argumentsNode
, unsigned additionalArguments
)
424 : m_argumentsNode(argumentsNode
)
427 if (generator
.shouldEmitProfileHooks())
428 m_profileHookRegister
= generator
.newTemporary();
430 size_t argumentCountIncludingThis
= 1 + additionalArguments
; // 'this' register.
432 for (ArgumentListNode
* node
= argumentsNode
->m_listNode
; node
; node
= node
->m_next
)
433 ++argumentCountIncludingThis
;
436 m_argv
.grow(argumentCountIncludingThis
);
437 for (int i
= argumentCountIncludingThis
- 1; i
>= 0; --i
) {
438 m_argv
[i
] = generator
.newTemporary();
439 ASSERT(static_cast<size_t>(i
) == m_argv
.size() - 1 || m_argv
[i
]->index() == m_argv
[i
+ 1]->index() - 1);
442 while (stackOffset() % stackAlignmentRegisters()) {
443 m_argv
.insert(0, generator
.newTemporary());
448 // ------------------------------ EvalFunctionCallNode ----------------------------------
450 RegisterID
* EvalFunctionCallNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
452 if (Local local
= generator
.local(generator
.propertyNames().eval
)) {
453 RefPtr
<RegisterID
> func
= generator
.emitMove(generator
.tempDestination(dst
), local
.get());
454 CallArguments
callArguments(generator
, m_args
);
455 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
456 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), callArguments
, divot(), divotStart(), divotEnd());
459 RefPtr
<RegisterID
> func
= generator
.newTemporary();
460 CallArguments
callArguments(generator
, m_args
);
461 JSTextPosition newDivot
= divotStart() + 4;
462 generator
.emitExpressionInfo(newDivot
, divotStart(), newDivot
);
463 generator
.emitResolveScope(callArguments
.thisRegister(), generator
.propertyNames().eval
);
464 generator
.emitGetFromScope(func
.get(), callArguments
.thisRegister(), generator
.propertyNames().eval
, ThrowIfNotFound
);
465 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), callArguments
, divot(), divotStart(), divotEnd());
468 // ------------------------------ FunctionCallValueNode ----------------------------------
470 RegisterID
* FunctionCallValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
472 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
473 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
474 CallArguments
callArguments(generator
, m_args
);
475 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
476 return generator
.emitCall(returnValue
.get(), func
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
479 // ------------------------------ FunctionCallResolveNode ----------------------------------
481 RegisterID
* FunctionCallResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
483 ExpectedFunction expectedFunction
= generator
.expectedFunctionForIdentifier(m_ident
);
485 if (Local local
= generator
.local(m_ident
)) {
486 RefPtr
<RegisterID
> func
= generator
.emitMove(generator
.tempDestination(dst
), local
.get());
487 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
488 CallArguments
callArguments(generator
, m_args
);
489 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
490 // This passes NoExpectedFunction because we expect that if the function is in a
491 // local variable, then it's not one of our built-in constructors.
492 return generator
.emitCall(returnValue
.get(), func
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
495 RefPtr
<RegisterID
> func
= generator
.newTemporary();
496 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
497 CallArguments
callArguments(generator
, m_args
);
499 JSTextPosition newDivot
= divotStart() + m_ident
.length();
500 generator
.emitExpressionInfo(newDivot
, divotStart(), newDivot
);
501 generator
.emitResolveScope(callArguments
.thisRegister(), m_ident
);
502 generator
.emitGetFromScope(func
.get(), callArguments
.thisRegister(), m_ident
, ThrowIfNotFound
);
503 return generator
.emitCall(returnValue
.get(), func
.get(), expectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
506 // ------------------------------ FunctionCallBracketNode ----------------------------------
508 RegisterID
* FunctionCallBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
510 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
511 RegisterID
* property
= generator
.emitNode(m_subscript
);
512 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
513 RefPtr
<RegisterID
> function
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
);
514 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, function
.get());
515 CallArguments
callArguments(generator
, m_args
);
516 generator
.emitMove(callArguments
.thisRegister(), base
.get());
517 return generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
520 // ------------------------------ FunctionCallDotNode ----------------------------------
522 RegisterID
* FunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
524 RefPtr
<RegisterID
> function
= generator
.tempDestination(dst
);
525 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, function
.get());
526 CallArguments
callArguments(generator
, m_args
);
527 generator
.emitNode(callArguments
.thisRegister(), m_base
);
528 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
529 generator
.emitGetById(function
.get(), callArguments
.thisRegister(), m_ident
);
530 return generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
533 static RegisterID
* getArgumentByVal(BytecodeGenerator
& generator
, ExpressionNode
* base
, RegisterID
* property
, RegisterID
* dst
, JSTextPosition divot
, JSTextPosition divotStart
, JSTextPosition divotEnd
)
535 if (base
->isResolveNode()
536 && generator
.willResolveToArguments(static_cast<ResolveNode
*>(base
)->identifier())
537 && !generator
.symbolTable().slowArguments()) {
538 generator
.emitExpressionInfo(divot
, divotStart
, divotEnd
);
539 return generator
.emitGetArgumentByVal(generator
.finalDestination(dst
), generator
.uncheckedRegisterForArguments(), property
);
544 RegisterID
* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
546 RefPtr
<Label
> realCall
= generator
.newLabel();
547 RefPtr
<Label
> end
= generator
.newLabel();
548 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
549 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
550 RefPtr
<RegisterID
> function
;
551 bool emitCallCheck
= !generator
.isBuiltinFunction();
553 function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), generator
.propertyNames().builtinNames().callPublicName());
554 generator
.emitJumpIfNotFunctionCall(function
.get(), realCall
.get());
556 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
);
558 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
&& m_args
->m_listNode
->m_expr
->isSpreadExpression()) {
559 RefPtr
<RegisterID
> profileHookRegister
;
560 if (generator
.shouldEmitProfileHooks())
561 profileHookRegister
= generator
.newTemporary();
562 SpreadExpressionNode
* spread
= static_cast<SpreadExpressionNode
*>(m_args
->m_listNode
->m_expr
);
563 ExpressionNode
* subject
= spread
->expression();
564 RefPtr
<RegisterID
> thisRegister
= getArgumentByVal(generator
, subject
, generator
.emitLoad(0, jsNumber(0)), 0, spread
->divot(), spread
->divotStart(), spread
->divotEnd());
565 RefPtr
<RegisterID
> argumentsRegister
;
567 argumentsRegister
= generator
.uncheckedRegisterForArguments();
569 argumentsRegister
= generator
.emitNode(subject
);
570 generator
.emitExpressionInfo(spread
->divot(), spread
->divotStart(), spread
->divotEnd());
571 thisRegister
= generator
.emitGetByVal(generator
.newTemporary(), argumentsRegister
.get(), generator
.emitLoad(0, jsNumber(0)));
573 generator
.emitCallVarargs(returnValue
.get(), base
.get(), thisRegister
.get(), argumentsRegister
.get(), generator
.newTemporary(), 1, profileHookRegister
.get(), divot(), divotStart(), divotEnd());
574 } else if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
575 ArgumentListNode
* oldList
= m_args
->m_listNode
;
576 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
578 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
579 CallArguments
callArguments(generator
, m_args
);
580 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
581 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
582 m_args
->m_listNode
= oldList
;
584 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
585 CallArguments
callArguments(generator
, m_args
);
586 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
587 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
591 generator
.emitJump(end
.get());
592 generator
.emitLabel(realCall
.get());
594 CallArguments
callArguments(generator
, m_args
);
595 generator
.emitMove(callArguments
.thisRegister(), base
.get());
596 generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
598 generator
.emitLabel(end
.get());
600 return returnValue
.get();
603 static bool areTrivialApplyArguments(ArgumentsNode
* args
)
605 return !args
->m_listNode
|| !args
->m_listNode
->m_expr
|| !args
->m_listNode
->m_next
606 || (!args
->m_listNode
->m_next
->m_next
&& args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
609 RegisterID
* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
611 // A few simple cases can be trivially handled as ordinary function calls.
612 // function.apply(), function.apply(arg) -> identical to function.call
613 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
614 bool mayBeCall
= areTrivialApplyArguments(m_args
);
616 RefPtr
<Label
> realCall
= generator
.newLabel();
617 RefPtr
<Label
> end
= generator
.newLabel();
618 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
619 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
620 RefPtr
<RegisterID
> function
;
621 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, function
.get());
622 bool emitCallCheck
= !generator
.isBuiltinFunction();
624 function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), generator
.propertyNames().builtinNames().applyPublicName());
625 generator
.emitJumpIfNotFunctionApply(function
.get(), realCall
.get());
628 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
629 ArgumentListNode
* oldList
= m_args
->m_listNode
;
630 if (m_args
->m_listNode
->m_expr
->isSpreadExpression()) {
631 SpreadExpressionNode
* spread
= static_cast<SpreadExpressionNode
*>(m_args
->m_listNode
->m_expr
);
632 RefPtr
<RegisterID
> profileHookRegister
;
633 if (generator
.shouldEmitProfileHooks())
634 profileHookRegister
= generator
.newTemporary();
635 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.newTemporary(), base
.get());
636 RefPtr
<RegisterID
> index
= generator
.emitLoad(generator
.newTemporary(), jsNumber(0));
637 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsUndefined());
638 RefPtr
<RegisterID
> argumentsRegister
= generator
.emitLoad(generator
.newTemporary(), jsUndefined());
640 auto extractor
= [&thisRegister
, &argumentsRegister
, &index
](BytecodeGenerator
& generator
, RegisterID
* value
)
642 RefPtr
<Label
> haveThis
= generator
.newLabel();
643 RefPtr
<Label
> end
= generator
.newLabel();
644 RefPtr
<RegisterID
> compareResult
= generator
.newTemporary();
645 RefPtr
<RegisterID
> indexZeroCompareResult
= generator
.emitBinaryOp(op_eq
, compareResult
.get(), index
.get(), generator
.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
646 generator
.emitJumpIfFalse(indexZeroCompareResult
.get(), haveThis
.get());
647 generator
.emitMove(thisRegister
.get(), value
);
648 generator
.emitLoad(index
.get(), jsNumber(1));
649 generator
.emitJump(end
.get());
650 generator
.emitLabel(haveThis
.get());
651 RefPtr
<RegisterID
> indexOneCompareResult
= generator
.emitBinaryOp(op_eq
, compareResult
.get(), index
.get(), generator
.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
652 generator
.emitJumpIfFalse(indexOneCompareResult
.get(), end
.get());
653 generator
.emitMove(argumentsRegister
.get(), value
);
654 generator
.emitLoad(index
.get(), jsNumber(2));
655 generator
.emitLabel(end
.get());
657 generator
.emitEnumeration(this, spread
->expression(), extractor
);
658 generator
.emitCallVarargs(returnValue
.get(), realFunction
.get(), thisRegister
.get(), argumentsRegister
.get(), generator
.newTemporary(), 0, profileHookRegister
.get(), divot(), divotStart(), divotEnd());
659 } else if (m_args
->m_listNode
->m_next
) {
660 ASSERT(m_args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
661 ASSERT(!m_args
->m_listNode
->m_next
->m_next
);
662 m_args
->m_listNode
= static_cast<ArrayNode
*>(m_args
->m_listNode
->m_next
->m_expr
)->toArgumentList(generator
.vm(), 0, 0);
663 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
664 CallArguments
callArguments(generator
, m_args
);
665 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
666 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
668 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
669 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
670 CallArguments
callArguments(generator
, m_args
);
671 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
672 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
674 m_args
->m_listNode
= oldList
;
676 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
677 CallArguments
callArguments(generator
, m_args
);
678 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
679 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
682 ASSERT(m_args
->m_listNode
&& m_args
->m_listNode
->m_next
);
683 RefPtr
<RegisterID
> profileHookRegister
;
684 if (generator
.shouldEmitProfileHooks())
685 profileHookRegister
= generator
.newTemporary();
686 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
687 RefPtr
<RegisterID
> thisRegister
= generator
.emitNode(m_args
->m_listNode
->m_expr
);
688 RefPtr
<RegisterID
> argsRegister
;
689 ArgumentListNode
* args
= m_args
->m_listNode
->m_next
;
690 if (args
->m_expr
->isResolveNode() && generator
.willResolveToArguments(static_cast<ResolveNode
*>(args
->m_expr
)->identifier()) && !generator
.symbolTable().slowArguments())
691 argsRegister
= generator
.uncheckedRegisterForArguments();
693 argsRegister
= generator
.emitNode(args
->m_expr
);
695 // Function.prototype.apply ignores extra arguments, but we still
696 // need to evaluate them for side effects.
697 while ((args
= args
->m_next
))
698 generator
.emitNode(args
->m_expr
);
700 generator
.emitCallVarargs(returnValue
.get(), realFunction
.get(), thisRegister
.get(), argsRegister
.get(), generator
.newTemporary(), 0, profileHookRegister
.get(), divot(), divotStart(), divotEnd());
703 generator
.emitJump(end
.get());
704 generator
.emitLabel(realCall
.get());
705 CallArguments
callArguments(generator
, m_args
);
706 generator
.emitMove(callArguments
.thisRegister(), base
.get());
707 generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
708 generator
.emitLabel(end
.get());
710 return returnValue
.get();
713 // ------------------------------ PostfixNode ----------------------------------
715 static RegisterID
* emitIncOrDec(BytecodeGenerator
& generator
, RegisterID
* srcDst
, Operator oper
)
717 return (oper
== OpPlusPlus
) ? generator
.emitInc(srcDst
) : generator
.emitDec(srcDst
);
720 static RegisterID
* emitPostIncOrDec(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* srcDst
, Operator oper
)
723 return generator
.emitToNumber(generator
.finalDestination(dst
), srcDst
);
724 RefPtr
<RegisterID
> tmp
= generator
.emitToNumber(generator
.tempDestination(dst
), srcDst
);
725 emitIncOrDec(generator
, srcDst
, oper
);
726 return generator
.moveToDestinationIfNeeded(dst
, tmp
.get());
729 RegisterID
* PostfixNode::emitResolve(BytecodeGenerator
& generator
, RegisterID
* dst
)
731 if (dst
== generator
.ignoredResult())
732 return PrefixNode::emitResolve(generator
, dst
);
734 ASSERT(m_expr
->isResolveNode());
735 ResolveNode
* resolve
= static_cast<ResolveNode
*>(m_expr
);
736 const Identifier
& ident
= resolve
->identifier();
738 if (Local local
= generator
.local(ident
)) {
739 RegisterID
* localReg
= local
.get();
740 if (local
.isReadOnly()) {
741 generator
.emitReadOnlyExceptionIfNeeded();
742 localReg
= generator
.emitMove(generator
.tempDestination(dst
), localReg
);
743 } else if (local
.isCaptured()) {
744 RefPtr
<RegisterID
> tempDst
= generator
.finalDestination(dst
);
745 ASSERT(dst
!= localReg
);
746 RefPtr
<RegisterID
> tempDstSrc
= generator
.newTemporary();
747 generator
.emitToNumber(tempDst
.get(), localReg
);
748 generator
.emitMove(tempDstSrc
.get(), localReg
);
749 emitIncOrDec(generator
, tempDstSrc
.get(), m_operator
);
750 generator
.emitMove(localReg
, tempDstSrc
.get());
751 return tempDst
.get();
753 return emitPostIncOrDec(generator
, generator
.finalDestination(dst
), localReg
, m_operator
);
756 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
757 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.newTemporary(), ident
);
758 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), ident
, ThrowIfNotFound
);
759 RefPtr
<RegisterID
> oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
760 generator
.emitPutToScope(scope
.get(), ident
, value
.get(), ThrowIfNotFound
);
761 return oldValue
.get();
764 RegisterID
* PostfixNode::emitBracket(BytecodeGenerator
& generator
, RegisterID
* dst
)
766 if (dst
== generator
.ignoredResult())
767 return PrefixNode::emitBracket(generator
, dst
);
769 ASSERT(m_expr
->isBracketAccessorNode());
770 BracketAccessorNode
* bracketAccessor
= static_cast<BracketAccessorNode
*>(m_expr
);
771 ExpressionNode
* baseNode
= bracketAccessor
->base();
772 ExpressionNode
* subscript
= bracketAccessor
->subscript();
774 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(baseNode
, bracketAccessor
->subscriptHasAssignments(), subscript
->isPure(generator
));
775 RefPtr
<RegisterID
> property
= generator
.emitNode(subscript
);
777 generator
.emitExpressionInfo(bracketAccessor
->divot(), bracketAccessor
->divotStart(), bracketAccessor
->divotEnd());
778 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.newTemporary(), base
.get(), property
.get());
779 RegisterID
* oldValue
= emitPostIncOrDec(generator
, generator
.tempDestination(dst
), value
.get(), m_operator
);
780 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
781 generator
.emitPutByVal(base
.get(), property
.get(), value
.get());
782 return generator
.moveToDestinationIfNeeded(dst
, oldValue
);
785 RegisterID
* PostfixNode::emitDot(BytecodeGenerator
& generator
, RegisterID
* dst
)
787 if (dst
== generator
.ignoredResult())
788 return PrefixNode::emitDot(generator
, dst
);
790 ASSERT(m_expr
->isDotAccessorNode());
791 DotAccessorNode
* dotAccessor
= static_cast<DotAccessorNode
*>(m_expr
);
792 ExpressionNode
* baseNode
= dotAccessor
->base();
793 const Identifier
& ident
= dotAccessor
->identifier();
795 RefPtr
<RegisterID
> base
= generator
.emitNode(baseNode
);
797 generator
.emitExpressionInfo(dotAccessor
->divot(), dotAccessor
->divotStart(), dotAccessor
->divotEnd());
798 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.newTemporary(), base
.get(), ident
);
799 RegisterID
* oldValue
= emitPostIncOrDec(generator
, generator
.tempDestination(dst
), value
.get(), m_operator
);
800 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
801 generator
.emitPutById(base
.get(), ident
, value
.get());
802 return generator
.moveToDestinationIfNeeded(dst
, oldValue
);
805 RegisterID
* PostfixNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
807 if (m_expr
->isResolveNode())
808 return emitResolve(generator
, dst
);
810 if (m_expr
->isBracketAccessorNode())
811 return emitBracket(generator
, dst
);
813 if (m_expr
->isDotAccessorNode())
814 return emitDot(generator
, dst
);
816 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
817 ? "Postfix ++ operator applied to value that is not a reference."
818 : "Postfix -- operator applied to value that is not a reference.");
821 // ------------------------------ DeleteResolveNode -----------------------------------
823 RegisterID
* DeleteResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
825 if (generator
.local(m_ident
).get())
826 return generator
.emitLoad(generator
.finalDestination(dst
), false);
828 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
829 RefPtr
<RegisterID
> base
= generator
.emitResolveScope(generator
.tempDestination(dst
), m_ident
);
830 return generator
.emitDeleteById(generator
.finalDestination(dst
, base
.get()), base
.get(), m_ident
);
833 // ------------------------------ DeleteBracketNode -----------------------------------
835 RegisterID
* DeleteBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
837 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
838 RegisterID
* r1
= generator
.emitNode(m_subscript
);
840 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
841 return generator
.emitDeleteByVal(generator
.finalDestination(dst
), r0
.get(), r1
);
844 // ------------------------------ DeleteDotNode -----------------------------------
846 RegisterID
* DeleteDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
848 RegisterID
* r0
= generator
.emitNode(m_base
);
850 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
851 return generator
.emitDeleteById(generator
.finalDestination(dst
), r0
, m_ident
);
854 // ------------------------------ DeleteValueNode -----------------------------------
856 RegisterID
* DeleteValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
858 generator
.emitNode(generator
.ignoredResult(), m_expr
);
860 // delete on a non-location expression ignores the value and returns true
861 return generator
.emitLoad(generator
.finalDestination(dst
), true);
864 // ------------------------------ VoidNode -------------------------------------
866 RegisterID
* VoidNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
868 if (dst
== generator
.ignoredResult()) {
869 generator
.emitNode(generator
.ignoredResult(), m_expr
);
872 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
873 return generator
.emitLoad(dst
, jsUndefined());
876 // ------------------------------ TypeOfValueNode -----------------------------------
878 RegisterID
* TypeOfResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
880 if (Local local
= generator
.local(m_ident
)) {
881 if (dst
== generator
.ignoredResult())
883 return generator
.emitTypeOf(generator
.finalDestination(dst
), local
.get());
886 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.tempDestination(dst
), m_ident
);
887 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), m_ident
, DoNotThrowIfNotFound
);
888 if (dst
== generator
.ignoredResult())
890 return generator
.emitTypeOf(generator
.finalDestination(dst
, scope
.get()), value
.get());
893 // ------------------------------ TypeOfValueNode -----------------------------------
895 RegisterID
* TypeOfValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
897 if (dst
== generator
.ignoredResult()) {
898 generator
.emitNode(generator
.ignoredResult(), m_expr
);
901 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
902 return generator
.emitTypeOf(generator
.finalDestination(dst
), src
.get());
905 // ------------------------------ PrefixNode ----------------------------------
907 RegisterID
* PrefixNode::emitResolve(BytecodeGenerator
& generator
, RegisterID
* dst
)
909 ASSERT(m_expr
->isResolveNode());
910 ResolveNode
* resolve
= static_cast<ResolveNode
*>(m_expr
);
911 const Identifier
& ident
= resolve
->identifier();
913 if (Local local
= generator
.local(ident
)) {
914 RegisterID
* localReg
= local
.get();
915 if (local
.isReadOnly()) {
916 generator
.emitReadOnlyExceptionIfNeeded();
917 localReg
= generator
.emitMove(generator
.tempDestination(dst
), localReg
);
918 } else if (local
.isCaptured()) {
919 RefPtr
<RegisterID
> tempDst
= generator
.tempDestination(dst
);
920 generator
.emitMove(tempDst
.get(), localReg
);
921 emitIncOrDec(generator
, tempDst
.get(), m_operator
);
922 generator
.emitMove(localReg
, tempDst
.get());
923 return generator
.moveToDestinationIfNeeded(dst
, tempDst
.get());
925 emitIncOrDec(generator
, localReg
, m_operator
);
926 return generator
.moveToDestinationIfNeeded(dst
, localReg
);
929 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
930 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.tempDestination(dst
), ident
);
931 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), ident
, ThrowIfNotFound
);
932 emitIncOrDec(generator
, value
.get(), m_operator
);
933 generator
.emitPutToScope(scope
.get(), ident
, value
.get(), ThrowIfNotFound
);
934 return generator
.moveToDestinationIfNeeded(dst
, value
.get());
937 RegisterID
* PrefixNode::emitBracket(BytecodeGenerator
& generator
, RegisterID
* dst
)
939 ASSERT(m_expr
->isBracketAccessorNode());
940 BracketAccessorNode
* bracketAccessor
= static_cast<BracketAccessorNode
*>(m_expr
);
941 ExpressionNode
* baseNode
= bracketAccessor
->base();
942 ExpressionNode
* subscript
= bracketAccessor
->subscript();
944 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(baseNode
, bracketAccessor
->subscriptHasAssignments(), subscript
->isPure(generator
));
945 RefPtr
<RegisterID
> property
= generator
.emitNode(subscript
);
946 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
948 generator
.emitExpressionInfo(bracketAccessor
->divot(), bracketAccessor
->divotStart(), bracketAccessor
->divotEnd());
949 RegisterID
* value
= generator
.emitGetByVal(propDst
.get(), base
.get(), property
.get());
950 emitIncOrDec(generator
, value
, m_operator
);
951 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
952 generator
.emitPutByVal(base
.get(), property
.get(), value
);
953 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
956 RegisterID
* PrefixNode::emitDot(BytecodeGenerator
& generator
, RegisterID
* dst
)
958 ASSERT(m_expr
->isDotAccessorNode());
959 DotAccessorNode
* dotAccessor
= static_cast<DotAccessorNode
*>(m_expr
);
960 ExpressionNode
* baseNode
= dotAccessor
->base();
961 const Identifier
& ident
= dotAccessor
->identifier();
963 RefPtr
<RegisterID
> base
= generator
.emitNode(baseNode
);
964 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
966 generator
.emitExpressionInfo(dotAccessor
->divot(), dotAccessor
->divotStart(), dotAccessor
->divotEnd());
967 RegisterID
* value
= generator
.emitGetById(propDst
.get(), base
.get(), ident
);
968 emitIncOrDec(generator
, value
, m_operator
);
969 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
970 generator
.emitPutById(base
.get(), ident
, value
);
971 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
974 RegisterID
* PrefixNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
976 if (m_expr
->isResolveNode())
977 return emitResolve(generator
, dst
);
979 if (m_expr
->isBracketAccessorNode())
980 return emitBracket(generator
, dst
);
982 if (m_expr
->isDotAccessorNode())
983 return emitDot(generator
, dst
);
985 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
986 ? "Prefix ++ operator applied to value that is not a reference."
987 : "Prefix -- operator applied to value that is not a reference.");
990 // ------------------------------ Unary Operation Nodes -----------------------------------
992 RegisterID
* UnaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
994 RegisterID
* src
= generator
.emitNode(m_expr
);
995 generator
.emitExpressionInfo(position(), position(), position());
996 return generator
.emitUnaryOp(opcodeID(), generator
.finalDestination(dst
), src
);
999 // ------------------------------ BitwiseNotNode -----------------------------------
1001 RegisterID
* BitwiseNotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1003 RefPtr
<RegisterID
> src2
= generator
.emitLoad(generator
.newTemporary(), jsNumber(-1));
1004 RegisterID
* src1
= generator
.emitNode(m_expr
);
1005 return generator
.emitBinaryOp(op_bitxor
, generator
.finalDestination(dst
, src1
), src1
, src2
.get(), OperandTypes(m_expr
->resultDescriptor(), ResultType::numberTypeIsInt32()));
1008 // ------------------------------ LogicalNotNode -----------------------------------
1010 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1012 // reverse the true and false targets
1013 generator
.emitNodeInConditionContext(expr(), falseTarget
, trueTarget
, invert(fallThroughMode
));
1017 // ------------------------------ Binary Operation Nodes -----------------------------------
1019 // BinaryOpNode::emitStrcat:
1021 // This node generates an op_strcat operation. This opcode can handle concatenation of three or
1022 // more values, where we can determine a set of separate op_add operations would be operating on
1025 // This function expects to be operating on a graph of AST nodes looking something like this:
1035 // The assignment operation is optional, if it exists the register holding the value on the
1036 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
1038 // The method should be called on the node at the root of the tree of regular binary add
1039 // operations (marked in the diagram with a double set of parentheses). This node must
1040 // be performing a string concatenation (determined by statically detecting that at least
1041 // one child must be a string).
1043 // Since the minimum number of values being concatenated together is expected to be 3, if
1044 // a lhs to a concatenating assignment is not provided then the root add should have at
1045 // least one left child that is also an add that can be determined to be operating on strings.
1047 RegisterID
* BinaryOpNode::emitStrcat(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* lhs
, ReadModifyResolveNode
* emitExpressionInfoForMe
)
1050 ASSERT(resultDescriptor().definitelyIsString());
1052 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1053 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1054 // added first, and the leftmost child is never added, so the vector produced for the
1055 // example above will be [ c, b ].
1056 Vector
<ExpressionNode
*, 16> reverseExpressionList
;
1057 reverseExpressionList
.append(m_expr2
);
1059 // Examine the left child of the add. So long as this is a string add, add its right-child
1060 // to the list, and keep processing along the left fork.
1061 ExpressionNode
* leftMostAddChild
= m_expr1
;
1062 while (leftMostAddChild
->isAdd() && leftMostAddChild
->resultDescriptor().definitelyIsString()) {
1063 reverseExpressionList
.append(static_cast<AddNode
*>(leftMostAddChild
)->m_expr2
);
1064 leftMostAddChild
= static_cast<AddNode
*>(leftMostAddChild
)->m_expr1
;
1067 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
1069 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1070 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1071 // op_strcat node handle its conversion if required).
1073 temporaryRegisters
.append(generator
.newTemporary());
1075 // Emit code for the leftmost node ((a) in the example).
1076 temporaryRegisters
.append(generator
.newTemporary());
1077 RegisterID
* leftMostAddChildTempRegister
= temporaryRegisters
.last().get();
1078 generator
.emitNode(leftMostAddChildTempRegister
, leftMostAddChild
);
1080 // Note on ordering of conversions:
1082 // We maintain the same ordering of conversions as we would see if the concatenations
1083 // was performed as a sequence of adds (otherwise this optimization could change
1084 // behaviour should an object have been provided a valueOf or toString method).
1086 // Considering the above example, the sequnce of execution is:
1087 // * evaluate operand (a)
1088 // * evaluate operand (b)
1089 // * convert (a) to primitive <- (this would be triggered by the first add)
1090 // * convert (b) to primitive <- (ditto)
1091 // * evaluate operand (c)
1092 // * convert (c) to primitive <- (this would be triggered by the second add)
1093 // And optionally, if there is an assignment:
1094 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1096 // As such we do not plant an op to convert the leftmost child now. Instead, use
1097 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1098 // once the second node has been generated. However, if the leftmost child is an
1099 // immediate we can trivially determine that no conversion will be required.
1100 // If this is the case
1101 if (leftMostAddChild
->isString())
1102 leftMostAddChildTempRegister
= 0;
1104 while (reverseExpressionList
.size()) {
1105 ExpressionNode
* node
= reverseExpressionList
.last();
1106 reverseExpressionList
.removeLast();
1108 // Emit the code for the current node.
1109 temporaryRegisters
.append(generator
.newTemporary());
1110 generator
.emitNode(temporaryRegisters
.last().get(), node
);
1112 // On the first iteration of this loop, when we first reach this point we have just
1113 // generated the second node, which means it is time to convert the leftmost operand.
1114 if (leftMostAddChildTempRegister
) {
1115 generator
.emitToPrimitive(leftMostAddChildTempRegister
, leftMostAddChildTempRegister
);
1116 leftMostAddChildTempRegister
= 0; // Only do this once.
1118 // Plant a conversion for this node, if necessary.
1119 if (!node
->isString())
1120 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
1122 ASSERT(temporaryRegisters
.size() >= 3);
1124 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1125 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1126 if (emitExpressionInfoForMe
)
1127 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->divotStart(), emitExpressionInfoForMe
->divotEnd());
1128 // If there is an assignment convert the lhs now. This will also copy lhs to
1129 // the temporary register we allocated for it.
1131 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
1133 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
1136 void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1138 TriState branchCondition
;
1139 ExpressionNode
* branchExpression
;
1140 tryFoldToBranch(generator
, branchCondition
, branchExpression
);
1142 if (branchCondition
== MixedTriState
)
1143 ExpressionNode::emitBytecodeInConditionContext(generator
, trueTarget
, falseTarget
, fallThroughMode
);
1144 else if (branchCondition
== TrueTriState
)
1145 generator
.emitNodeInConditionContext(branchExpression
, trueTarget
, falseTarget
, fallThroughMode
);
1147 generator
.emitNodeInConditionContext(branchExpression
, falseTarget
, trueTarget
, invert(fallThroughMode
));
1150 static inline bool canFoldToBranch(OpcodeID opcodeID
, ExpressionNode
* branchExpression
, JSValue constant
)
1152 ResultType expressionType
= branchExpression
->resultDescriptor();
1154 if (expressionType
.definitelyIsBoolean() && constant
.isBoolean())
1156 else if (expressionType
.definitelyIsBoolean() && constant
.isInt32() && (constant
.asInt32() == 0 || constant
.asInt32() == 1))
1157 return opcodeID
== op_eq
|| opcodeID
== op_neq
; // Strict equality is false in the case of type mismatch.
1158 else if (expressionType
.isInt32() && constant
.isInt32() && constant
.asInt32() == 0)
1164 void BinaryOpNode::tryFoldToBranch(BytecodeGenerator
& generator
, TriState
& branchCondition
, ExpressionNode
*& branchExpression
)
1166 branchCondition
= MixedTriState
;
1167 branchExpression
= 0;
1169 ConstantNode
* constant
= 0;
1170 if (m_expr1
->isConstant()) {
1171 constant
= static_cast<ConstantNode
*>(m_expr1
);
1172 branchExpression
= m_expr2
;
1173 } else if (m_expr2
->isConstant()) {
1174 constant
= static_cast<ConstantNode
*>(m_expr2
);
1175 branchExpression
= m_expr1
;
1180 ASSERT(branchExpression
);
1182 OpcodeID opcodeID
= this->opcodeID();
1183 JSValue value
= constant
->jsValue(generator
);
1184 bool canFoldToBranch
= JSC::canFoldToBranch(opcodeID
, branchExpression
, value
);
1185 if (!canFoldToBranch
)
1188 if (opcodeID
== op_eq
|| opcodeID
== op_stricteq
)
1189 branchCondition
= triState(value
.pureToBoolean());
1190 else if (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
)
1191 branchCondition
= triState(!value
.pureToBoolean());
1194 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1196 OpcodeID opcodeID
= this->opcodeID();
1198 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString()) {
1199 generator
.emitExpressionInfo(position(), position(), position());
1200 return emitStrcat(generator
, dst
);
1203 if (opcodeID
== op_neq
) {
1204 if (m_expr1
->isNull() || m_expr2
->isNull()) {
1205 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
1206 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
1207 return generator
.emitUnaryOp(op_neq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
1211 ExpressionNode
* left
= m_expr1
;
1212 ExpressionNode
* right
= m_expr2
;
1213 if (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
) {
1214 if (left
->isString())
1215 std::swap(left
, right
);
1218 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, right
->isPure(generator
));
1219 bool wasTypeof
= generator
.m_lastOpcodeID
== op_typeof
;
1220 RegisterID
* src2
= generator
.emitNode(right
);
1221 generator
.emitExpressionInfo(position(), position(), position());
1222 if (wasTypeof
&& (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
)) {
1223 RefPtr
<RegisterID
> tmp
= generator
.tempDestination(dst
);
1224 if (opcodeID
== op_neq
)
1225 generator
.emitEqualityOp(op_eq
, generator
.finalDestination(tmp
.get(), src1
.get()), src1
.get(), src2
);
1226 else if (opcodeID
== op_nstricteq
)
1227 generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(tmp
.get(), src1
.get()), src1
.get(), src2
);
1229 RELEASE_ASSERT_NOT_REACHED();
1230 return generator
.emitUnaryOp(op_not
, generator
.finalDestination(dst
, tmp
.get()), tmp
.get());
1232 RegisterID
* result
= generator
.emitBinaryOp(opcodeID
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(left
->resultDescriptor(), right
->resultDescriptor()));
1233 if (opcodeID
== op_urshift
&& dst
!= generator
.ignoredResult())
1234 return generator
.emitUnaryOp(op_unsigned
, result
, result
);
1238 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1240 if (m_expr1
->isNull() || m_expr2
->isNull()) {
1241 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
1242 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
1243 return generator
.emitUnaryOp(op_eq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
1246 ExpressionNode
* left
= m_expr1
;
1247 ExpressionNode
* right
= m_expr2
;
1248 if (left
->isString())
1249 std::swap(left
, right
);
1251 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1252 RegisterID
* src2
= generator
.emitNode(right
);
1253 return generator
.emitEqualityOp(op_eq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
1256 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1258 ExpressionNode
* left
= m_expr1
;
1259 ExpressionNode
* right
= m_expr2
;
1260 if (left
->isString())
1261 std::swap(left
, right
);
1263 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1264 RegisterID
* src2
= generator
.emitNode(right
);
1265 return generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
1268 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1270 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1271 RegisterID
* src2
= generator
.emitNode(m_expr2
);
1272 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1273 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
1276 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1278 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1279 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
1280 RefPtr
<RegisterID
> prototype
= generator
.newTemporary();
1281 RefPtr
<RegisterID
> dstReg
= generator
.finalDestination(dst
, src1
.get());
1282 RefPtr
<Label
> target
= generator
.newLabel();
1284 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1285 generator
.emitCheckHasInstance(dstReg
.get(), src1
.get(), src2
.get(), target
.get());
1287 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1288 generator
.emitGetById(prototype
.get(), src2
.get(), generator
.vm()->propertyNames
->prototype
);
1290 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1291 RegisterID
* result
= generator
.emitInstanceOf(dstReg
.get(), src1
.get(), prototype
.get());
1292 generator
.emitLabel(target
.get());
1296 // ------------------------------ LogicalOpNode ----------------------------
1298 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1300 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
1301 RefPtr
<Label
> target
= generator
.newLabel();
1303 generator
.emitNode(temp
.get(), m_expr1
);
1304 if (m_operator
== OpLogicalAnd
)
1305 generator
.emitJumpIfFalse(temp
.get(), target
.get());
1307 generator
.emitJumpIfTrue(temp
.get(), target
.get());
1308 generator
.emitNode(temp
.get(), m_expr2
);
1309 generator
.emitLabel(target
.get());
1311 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
1314 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1316 RefPtr
<Label
> afterExpr1
= generator
.newLabel();
1317 if (m_operator
== OpLogicalAnd
)
1318 generator
.emitNodeInConditionContext(m_expr1
, afterExpr1
.get(), falseTarget
, FallThroughMeansTrue
);
1320 generator
.emitNodeInConditionContext(m_expr1
, trueTarget
, afterExpr1
.get(), FallThroughMeansFalse
);
1321 generator
.emitLabel(afterExpr1
.get());
1323 generator
.emitNodeInConditionContext(m_expr2
, trueTarget
, falseTarget
, fallThroughMode
);
1326 // ------------------------------ ConditionalNode ------------------------------
1328 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1330 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
1331 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1332 RefPtr
<Label
> afterElse
= generator
.newLabel();
1334 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1335 generator
.emitNodeInConditionContext(m_logical
, beforeThen
.get(), beforeElse
.get(), FallThroughMeansTrue
);
1336 generator
.emitLabel(beforeThen
.get());
1338 generator
.emitNode(newDst
.get(), m_expr1
);
1339 generator
.emitJump(afterElse
.get());
1341 generator
.emitLabel(beforeElse
.get());
1342 generator
.emitNode(newDst
.get(), m_expr2
);
1344 generator
.emitLabel(afterElse
.get());
1346 return newDst
.get();
1349 // ------------------------------ ReadModifyResolveNode -----------------------------------
1351 // FIXME: should this be moved to be a method on BytecodeGenerator?
1352 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1363 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1364 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1371 opcodeID
= op_lshift
;
1374 opcodeID
= op_rshift
;
1377 opcodeID
= op_urshift
;
1380 opcodeID
= op_bitand
;
1383 opcodeID
= op_bitxor
;
1386 opcodeID
= op_bitor
;
1392 RELEASE_ASSERT_NOT_REACHED();
1396 RegisterID
* src2
= generator
.emitNode(m_right
);
1398 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1399 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1400 if (emitExpressionInfoForMe
)
1401 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->divotStart(), emitExpressionInfoForMe
->divotEnd());
1402 RegisterID
* result
= generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1403 if (oper
== OpURShift
)
1404 return generator
.emitUnaryOp(op_unsigned
, result
, result
);
1408 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1410 if (Local local
= generator
.local(m_ident
)) {
1411 if (local
.isReadOnly()) {
1412 generator
.emitReadOnlyExceptionIfNeeded();
1413 return emitReadModifyAssignment(generator
, generator
.finalDestination(dst
), local
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1416 if (local
.isCaptured()
1417 || generator
.leftHandSideNeedsCopy(m_rightHasAssignments
, m_right
->isPure(generator
))) {
1418 RefPtr
<RegisterID
> result
= generator
.newTemporary();
1419 generator
.emitMove(result
.get(), local
.get());
1420 emitReadModifyAssignment(generator
, result
.get(), result
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1421 generator
.emitMove(local
.get(), result
.get());
1422 return generator
.moveToDestinationIfNeeded(dst
, result
.get());
1425 RegisterID
* result
= emitReadModifyAssignment(generator
, local
.get(), local
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1426 return generator
.moveToDestinationIfNeeded(dst
, result
);
1429 JSTextPosition newDivot
= divotStart() + m_ident
.length();
1430 generator
.emitExpressionInfo(newDivot
, divotStart(), newDivot
);
1431 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.newTemporary(), m_ident
);
1432 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), m_ident
, ThrowIfNotFound
);
1433 RefPtr
<RegisterID
> result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()), this);
1434 return generator
.emitPutToScope(scope
.get(), m_ident
, result
.get(), ThrowIfNotFound
);
1437 // ------------------------------ AssignResolveNode -----------------------------------
1439 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1441 if (Local local
= generator
.local(m_ident
)) {
1442 if (local
.isReadOnly()) {
1443 generator
.emitReadOnlyExceptionIfNeeded();
1444 return generator
.emitNode(dst
, m_right
);
1446 if (local
.isCaptured()) {
1447 RefPtr
<RegisterID
> tempDst
= generator
.tempDestination(dst
);
1448 generator
.emitNode(tempDst
.get(), m_right
);
1449 generator
.emitMove(local
.get(), tempDst
.get());
1450 return generator
.moveToDestinationIfNeeded(dst
, tempDst
.get());
1452 RegisterID
* result
= generator
.emitNode(local
.get(), m_right
);
1453 return generator
.moveToDestinationIfNeeded(dst
, result
);
1456 if (generator
.isStrictMode())
1457 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1458 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.newTemporary(), m_ident
);
1459 if (dst
== generator
.ignoredResult())
1461 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_right
);
1462 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1463 return generator
.emitPutToScope(scope
.get(), m_ident
, result
.get(), generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
1466 // ------------------------------ AssignDotNode -----------------------------------
1468 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1470 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1471 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1472 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1473 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1474 RegisterID
* forwardResult
= (dst
== generator
.ignoredResult()) ? result
: generator
.moveToDestinationIfNeeded(generator
.tempDestination(result
), result
);
1475 generator
.emitPutById(base
.get(), m_ident
, forwardResult
);
1476 return generator
.moveToDestinationIfNeeded(dst
, forwardResult
);
1479 // ------------------------------ ReadModifyDotNode -----------------------------------
1481 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1483 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1485 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1486 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
1487 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, static_cast<JSC::Operator
>(m_operator
), OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1489 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1490 return generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1493 // ------------------------------ AssignErrorNode -----------------------------------
1495 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1497 return emitThrowReferenceError(generator
, "Left side of assignment is not a reference.");
1500 // ------------------------------ AssignBracketNode -----------------------------------
1502 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1504 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1505 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1506 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1507 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1509 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1510 RegisterID
* forwardResult
= (dst
== generator
.ignoredResult()) ? result
: generator
.moveToDestinationIfNeeded(generator
.tempDestination(result
), result
);
1511 generator
.emitPutByVal(base
.get(), property
.get(), forwardResult
);
1512 return generator
.moveToDestinationIfNeeded(dst
, forwardResult
);
1515 // ------------------------------ ReadModifyBracketNode -----------------------------------
1517 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1519 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1520 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1522 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1523 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
1524 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, static_cast<JSC::Operator
>(m_operator
), OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1526 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1527 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1529 return updatedValue
;
1532 // ------------------------------ CommaNode ------------------------------------
1534 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1536 ASSERT(m_expressions
.size() > 1);
1537 for (size_t i
= 0; i
< m_expressions
.size() - 1; i
++)
1538 generator
.emitNode(generator
.ignoredResult(), m_expressions
[i
]);
1539 return generator
.emitNode(dst
, m_expressions
.last());
1542 // ------------------------------ ConstDeclNode ------------------------------------
1544 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1546 // FIXME: This code does not match the behavior of const in Firefox.
1547 if (Local local
= generator
.constLocal(m_ident
)) {
1551 if (local
.isCaptured()) {
1552 RefPtr
<RegisterID
> tempDst
= generator
.newTemporary();
1553 generator
.emitNode(tempDst
.get(), m_init
);
1554 return generator
.emitMove(local
.get(), tempDst
.get());
1557 return generator
.emitNode(local
.get(), m_init
);
1560 RefPtr
<RegisterID
> value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1562 if (generator
.codeType() == GlobalCode
)
1563 return generator
.emitInitGlobalConst(m_ident
, value
.get());
1565 if (generator
.codeType() != EvalCode
)
1568 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
1569 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.newTemporary(), m_ident
);
1570 return generator
.emitPutToScope(scope
.get(), m_ident
, value
.get(), DoNotThrowIfNotFound
);
1573 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1575 RegisterID
* result
= 0;
1576 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1577 result
= n
->emitCodeSingle(generator
);
1582 // ------------------------------ ConstStatementNode -----------------------------
1584 void ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1586 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1587 generator
.emitNode(m_next
);
1590 // ------------------------------ SourceElements -------------------------------
1593 inline StatementNode
* SourceElements::lastStatement() const
1595 size_t size
= m_statements
.size();
1596 return size
? m_statements
[size
- 1] : 0;
1599 inline void SourceElements::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1601 size_t size
= m_statements
.size();
1602 for (size_t i
= 0; i
< size
; ++i
)
1603 generator
.emitNode(dst
, m_statements
[i
]);
1606 // ------------------------------ BlockNode ------------------------------------
1608 inline StatementNode
* BlockNode::lastStatement() const
1610 return m_statements
? m_statements
->lastStatement() : 0;
1613 inline StatementNode
* BlockNode::singleStatement() const
1615 return m_statements
? m_statements
->singleStatement() : 0;
1618 void BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1622 m_statements
->emitBytecode(generator
, dst
);
1625 // ------------------------------ EmptyStatementNode ---------------------------
1627 void EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1629 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1632 // ------------------------------ DebuggerStatementNode ---------------------------
1634 void DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1636 generator
.emitDebugHook(DidReachBreakpoint
, lastLine(), startOffset(), lineStartOffset());
1639 // ------------------------------ ExprStatementNode ----------------------------
1641 void ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1644 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1645 generator
.emitNode(dst
, m_expr
);
1648 // ------------------------------ VarStatementNode ----------------------------
1650 void VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1653 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1654 generator
.emitNode(m_expr
);
1657 // ------------------------------ IfElseNode ---------------------------------------
1659 static inline StatementNode
* singleStatement(StatementNode
* statementNode
)
1661 if (statementNode
->isBlock())
1662 return static_cast<BlockNode
*>(statementNode
)->singleStatement();
1663 return statementNode
;
1666 bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator
& generator
, StatementNode
* ifBlock
,
1667 Label
*& trueTarget
, FallThroughMode
& fallThroughMode
)
1669 StatementNode
* singleStatement
= JSC::singleStatement(ifBlock
);
1670 if (!singleStatement
)
1673 if (singleStatement
->isBreak()) {
1674 BreakNode
* breakNode
= static_cast<BreakNode
*>(singleStatement
);
1675 Label
* target
= breakNode
->trivialTarget(generator
);
1678 trueTarget
= target
;
1679 fallThroughMode
= FallThroughMeansFalse
;
1683 if (singleStatement
->isContinue()) {
1684 ContinueNode
* continueNode
= static_cast<ContinueNode
*>(singleStatement
);
1685 Label
* target
= continueNode
->trivialTarget(generator
);
1688 trueTarget
= target
;
1689 fallThroughMode
= FallThroughMeansFalse
;
1696 void IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1698 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1700 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1701 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1702 RefPtr
<Label
> afterElse
= generator
.newLabel();
1704 Label
* trueTarget
= beforeThen
.get();
1705 Label
* falseTarget
= beforeElse
.get();
1706 FallThroughMode fallThroughMode
= FallThroughMeansTrue
;
1707 bool didFoldIfBlock
= tryFoldBreakAndContinue(generator
, m_ifBlock
, trueTarget
, fallThroughMode
);
1709 generator
.emitNodeInConditionContext(m_condition
, trueTarget
, falseTarget
, fallThroughMode
);
1710 generator
.emitLabel(beforeThen
.get());
1712 if (!didFoldIfBlock
) {
1713 generator
.emitNode(dst
, m_ifBlock
);
1715 generator
.emitJump(afterElse
.get());
1718 generator
.emitLabel(beforeElse
.get());
1721 generator
.emitNode(dst
, m_elseBlock
);
1723 generator
.emitLabel(afterElse
.get());
1726 // ------------------------------ DoWhileNode ----------------------------------
1728 void DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1730 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1732 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1733 generator
.emitLabel(topOfLoop
.get());
1734 generator
.emitLoopHint();
1735 generator
.emitDebugHook(WillExecuteStatement
, lastLine(), startOffset(), lineStartOffset());
1737 generator
.emitNode(dst
, m_statement
);
1739 generator
.emitLabel(scope
->continueTarget());
1740 generator
.emitDebugHook(WillExecuteStatement
, lastLine(), startOffset(), lineStartOffset());
1741 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
1743 generator
.emitLabel(scope
->breakTarget());
1746 // ------------------------------ WhileNode ------------------------------------
1748 void WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1750 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1751 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1753 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->startOffset(), m_expr
->lineStartOffset());
1754 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansTrue
);
1756 generator
.emitLabel(topOfLoop
.get());
1757 generator
.emitLoopHint();
1759 generator
.emitNode(dst
, m_statement
);
1761 generator
.emitLabel(scope
->continueTarget());
1762 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1764 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
1766 generator
.emitLabel(scope
->breakTarget());
1769 // ------------------------------ ForNode --------------------------------------
1771 void ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1773 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1775 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1778 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
1780 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1782 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansTrue
);
1784 generator
.emitLabel(topOfLoop
.get());
1785 generator
.emitLoopHint();
1787 generator
.emitNode(dst
, m_statement
);
1789 generator
.emitLabel(scope
->continueTarget());
1790 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1792 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
1795 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
1797 generator
.emitJump(topOfLoop
.get());
1799 generator
.emitLabel(scope
->breakTarget());
1802 // ------------------------------ ForInNode ------------------------------------
1804 void ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1806 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1808 if (!m_lexpr
->isAssignmentLocation()) {
1809 emitThrowReferenceError(generator
, "Left side of for-in statement is not a reference.");
1813 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1815 RefPtr
<RegisterID
> base
= generator
.newTemporary();
1816 generator
.emitNode(base
.get(), m_expr
);
1817 RefPtr
<RegisterID
> i
= generator
.newTemporary();
1818 RefPtr
<RegisterID
> size
= generator
.newTemporary();
1819 RefPtr
<RegisterID
> expectedSubscript
;
1820 RefPtr
<RegisterID
> iter
= generator
.emitGetPropertyNames(generator
.newTemporary(), base
.get(), i
.get(), size
.get(), scope
->breakTarget());
1821 generator
.emitJump(scope
->continueTarget());
1823 RefPtr
<Label
> loopStart
= generator
.newLabel();
1824 generator
.emitLabel(loopStart
.get());
1825 generator
.emitLoopHint();
1827 RegisterID
* propertyName
;
1828 bool optimizedForinAccess
= false;
1829 if (m_lexpr
->isResolveNode()) {
1830 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1831 Local local
= generator
.local(ident
);
1833 propertyName
= generator
.newTemporary();
1834 RefPtr
<RegisterID
> protect
= propertyName
;
1835 if (generator
.isStrictMode())
1836 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1837 RegisterID
* scope
= generator
.emitResolveScope(generator
.newTemporary(), ident
);
1838 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1839 generator
.emitPutToScope(scope
, ident
, propertyName
, generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
1841 expectedSubscript
= generator
.newTemporary();
1842 propertyName
= expectedSubscript
.get();
1843 generator
.emitMove(local
.get(), propertyName
);
1844 generator
.pushOptimisedForIn(expectedSubscript
.get(), iter
.get(), i
.get(), local
.get());
1845 optimizedForinAccess
= true;
1847 } else if (m_lexpr
->isDotAccessorNode()) {
1848 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1849 const Identifier
& ident
= assignNode
->identifier();
1850 propertyName
= generator
.newTemporary();
1851 RefPtr
<RegisterID
> protect
= propertyName
;
1852 RegisterID
* base
= generator
.emitNode(assignNode
->base());
1854 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
1855 generator
.emitPutById(base
, ident
, propertyName
);
1856 } else if (m_lexpr
->isBracketAccessorNode()) {
1857 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1858 propertyName
= generator
.newTemporary();
1859 RefPtr
<RegisterID
> protect
= propertyName
;
1860 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1861 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1863 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
1864 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
1866 ASSERT(m_lexpr
->isDeconstructionNode());
1867 DeconstructingAssignmentNode
* assignNode
= static_cast<DeconstructingAssignmentNode
*>(m_lexpr
);
1868 auto binding
= assignNode
->bindings();
1869 if (binding
->isBindingNode()) {
1870 auto simpleBinding
= static_cast<BindingNode
*>(binding
);
1871 Identifier ident
= simpleBinding
->boundProperty();
1872 Local local
= generator
.local(ident
);
1873 propertyName
= local
.get();
1874 if (!propertyName
|| local
.isCaptured())
1875 goto genericBinding
;
1876 expectedSubscript
= generator
.emitMove(generator
.newTemporary(), propertyName
);
1877 generator
.pushOptimisedForIn(expectedSubscript
.get(), iter
.get(), i
.get(), propertyName
);
1878 optimizedForinAccess
= true;
1879 goto completedSimpleBinding
;
1882 propertyName
= generator
.newTemporary();
1883 RefPtr
<RegisterID
> protect(propertyName
);
1884 assignNode
->bindings()->bindValue(generator
, propertyName
);
1886 completedSimpleBinding
:
1890 generator
.emitNode(dst
, m_statement
);
1892 if (optimizedForinAccess
)
1893 generator
.popOptimisedForIn();
1895 generator
.emitLabel(scope
->continueTarget());
1896 generator
.emitNextPropertyName(propertyName
, base
.get(), i
.get(), size
.get(), iter
.get(), loopStart
.get());
1897 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1898 generator
.emitLabel(scope
->breakTarget());
1901 // ------------------------------ ForOfNode ------------------------------------
1902 void ForOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1904 if (!m_lexpr
->isAssignmentLocation()) {
1905 emitThrowReferenceError(generator
, "Left side of for-of statement is not a reference.");
1909 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
1911 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1912 auto extractor
= [this, dst
](BytecodeGenerator
& generator
, RegisterID
* value
)
1914 if (m_lexpr
->isResolveNode()) {
1915 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1916 if (Local local
= generator
.local(ident
))
1917 generator
.emitMove(local
.get(), value
);
1919 if (generator
.isStrictMode())
1920 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1921 RegisterID
* scope
= generator
.emitResolveScope(generator
.newTemporary(), ident
);
1922 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1923 generator
.emitPutToScope(scope
, ident
, value
, generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
1925 } else if (m_lexpr
->isDotAccessorNode()) {
1926 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1927 const Identifier
& ident
= assignNode
->identifier();
1928 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1930 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
1931 generator
.emitPutById(base
.get(), ident
, value
);
1932 } else if (m_lexpr
->isBracketAccessorNode()) {
1933 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1934 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1935 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1937 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
1938 generator
.emitPutByVal(base
.get(), subscript
, value
);
1940 ASSERT(m_lexpr
->isDeconstructionNode());
1941 DeconstructingAssignmentNode
* assignNode
= static_cast<DeconstructingAssignmentNode
*>(m_lexpr
);
1942 assignNode
->bindings()->bindValue(generator
, value
);
1944 generator
.emitNode(dst
, m_statement
);
1946 generator
.emitEnumeration(this, m_expr
, extractor
);
1949 // ------------------------------ ContinueNode ---------------------------------
1951 Label
* ContinueNode::trivialTarget(BytecodeGenerator
& generator
)
1953 if (generator
.shouldEmitDebugHooks())
1956 LabelScopePtr scope
= generator
.continueTarget(m_ident
);
1959 if (generator
.scopeDepth() != scope
->scopeDepth())
1962 return scope
->continueTarget();
1965 void ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1967 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1969 LabelScopePtr scope
= generator
.continueTarget(m_ident
);
1972 generator
.emitPopScopes(scope
->scopeDepth());
1973 generator
.emitJump(scope
->continueTarget());
1976 // ------------------------------ BreakNode ------------------------------------
1978 Label
* BreakNode::trivialTarget(BytecodeGenerator
& generator
)
1980 if (generator
.shouldEmitDebugHooks())
1983 LabelScopePtr scope
= generator
.breakTarget(m_ident
);
1986 if (generator
.scopeDepth() != scope
->scopeDepth())
1989 return scope
->breakTarget();
1992 void BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1994 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
1996 LabelScopePtr scope
= generator
.breakTarget(m_ident
);
1999 generator
.emitPopScopes(scope
->scopeDepth());
2000 generator
.emitJump(scope
->breakTarget());
2003 // ------------------------------ ReturnNode -----------------------------------
2005 void ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2007 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2008 ASSERT(generator
.codeType() == FunctionCode
);
2010 if (dst
== generator
.ignoredResult())
2013 RefPtr
<RegisterID
> returnRegister
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
2014 if (generator
.scopeDepth()) {
2015 returnRegister
= generator
.emitMove(generator
.newTemporary(), returnRegister
.get());
2016 generator
.emitPopScopes(0);
2019 generator
.emitDebugHook(WillLeaveCallFrame
, lastLine(), startOffset(), lineStartOffset());
2020 generator
.emitReturn(returnRegister
.get());
2023 // ------------------------------ WithNode -------------------------------------
2025 void WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2027 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2029 RefPtr
<RegisterID
> scope
= generator
.emitNode(m_expr
);
2030 generator
.emitExpressionInfo(m_divot
, m_divot
- m_expressionLength
, m_divot
);
2031 generator
.emitPushWithScope(scope
.get());
2032 generator
.emitNode(dst
, m_statement
);
2033 generator
.emitPopScope();
2036 // ------------------------------ CaseClauseNode --------------------------------
2038 inline void CaseClauseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2042 m_statements
->emitBytecode(generator
, dst
);
2045 // ------------------------------ CaseBlockNode --------------------------------
2054 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
2056 for (; list
; list
= list
->getNext()) {
2057 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
2058 literalVector
.append(clauseExpression
);
2059 if (clauseExpression
->isNumber()) {
2060 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
2061 int32_t intVal
= static_cast<int32_t>(value
);
2062 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
2063 typeForTable
= SwitchNeither
;
2066 if (intVal
< min_num
)
2068 if (intVal
> max_num
)
2070 typeForTable
= SwitchNumber
;
2073 if (clauseExpression
->isString()) {
2074 if (typeForTable
& ~SwitchString
) {
2075 typeForTable
= SwitchNeither
;
2078 const String
& value
= static_cast<StringNode
*>(clauseExpression
)->value().string();
2079 if (singleCharacterSwitch
&= value
.length() == 1) {
2080 int32_t intVal
= value
[0];
2081 if (intVal
< min_num
)
2083 if (intVal
> max_num
)
2086 typeForTable
= SwitchString
;
2089 typeForTable
= SwitchNeither
;
2094 static inline size_t length(ClauseListNode
* list1
, ClauseListNode
* list2
)
2097 for (ClauseListNode
* node
= list1
; node
; node
= node
->getNext())
2099 for (ClauseListNode
* node
= list2
; node
; node
= node
->getNext())
2104 SwitchInfo::SwitchType
CaseBlockNode::tryTableSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
2106 if (length(m_list1
, m_list2
) < s_tableSwitchMinimum
)
2107 return SwitchInfo::SwitchNone
;
2109 SwitchKind typeForTable
= SwitchUnset
;
2110 bool singleCharacterSwitch
= true;
2112 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
2113 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
2115 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
2116 return SwitchInfo::SwitchNone
;
2118 if (typeForTable
== SwitchNumber
) {
2119 int32_t range
= max_num
- min_num
;
2120 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
2121 return SwitchInfo::SwitchImmediate
;
2122 return SwitchInfo::SwitchNone
;
2125 ASSERT(typeForTable
== SwitchString
);
2127 if (singleCharacterSwitch
) {
2128 int32_t range
= max_num
- min_num
;
2129 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
2130 return SwitchInfo::SwitchCharacter
;
2133 return SwitchInfo::SwitchString
;
2136 void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
2138 RefPtr
<Label
> defaultLabel
;
2139 Vector
<RefPtr
<Label
>, 8> labelVector
;
2140 Vector
<ExpressionNode
*, 8> literalVector
;
2141 int32_t min_num
= std::numeric_limits
<int32_t>::max();
2142 int32_t max_num
= std::numeric_limits
<int32_t>::min();
2143 SwitchInfo::SwitchType switchType
= tryTableSwitch(literalVector
, min_num
, max_num
);
2145 if (switchType
!= SwitchInfo::SwitchNone
) {
2146 // Prepare the various labels
2147 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
2148 labelVector
.append(generator
.newLabel());
2149 defaultLabel
= generator
.newLabel();
2150 generator
.beginSwitch(switchExpression
, switchType
);
2153 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
2154 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
2155 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
2156 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
2157 labelVector
.append(generator
.newLabel());
2158 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
2161 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
2162 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
2163 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
2164 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
2165 labelVector
.append(generator
.newLabel());
2166 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
2168 defaultLabel
= generator
.newLabel();
2169 generator
.emitJump(defaultLabel
.get());
2173 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
2174 generator
.emitLabel(labelVector
[i
++].get());
2175 list
->getClause()->emitBytecode(generator
, dst
);
2178 if (m_defaultClause
) {
2179 generator
.emitLabel(defaultLabel
.get());
2180 m_defaultClause
->emitBytecode(generator
, dst
);
2183 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
2184 generator
.emitLabel(labelVector
[i
++].get());
2185 list
->getClause()->emitBytecode(generator
, dst
);
2187 if (!m_defaultClause
)
2188 generator
.emitLabel(defaultLabel
.get());
2190 ASSERT(i
== labelVector
.size());
2191 if (switchType
!= SwitchInfo::SwitchNone
) {
2192 ASSERT(labelVector
.size() == literalVector
.size());
2193 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
2197 // ------------------------------ SwitchNode -----------------------------------
2199 void SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2201 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2203 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Switch
);
2205 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
2206 m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
2208 generator
.emitLabel(scope
->breakTarget());
2211 // ------------------------------ LabelNode ------------------------------------
2213 void LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2215 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2217 ASSERT(!generator
.breakTarget(m_name
));
2219 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
2220 generator
.emitNode(dst
, m_statement
);
2222 generator
.emitLabel(scope
->breakTarget());
2225 // ------------------------------ ThrowNode ------------------------------------
2227 void ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2229 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2231 if (dst
== generator
.ignoredResult())
2233 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
2234 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
2235 generator
.emitThrow(expr
.get());
2238 // ------------------------------ TryNode --------------------------------------
2240 void TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2242 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2243 // optimizer knows they may be jumped to from anywhere.
2245 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2247 ASSERT(m_catchBlock
|| m_finallyBlock
);
2249 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
2250 generator
.emitLabel(tryStartLabel
.get());
2253 generator
.pushFinallyContext(m_finallyBlock
);
2254 TryData
* tryData
= generator
.pushTry(tryStartLabel
.get());
2256 generator
.emitNode(dst
, m_tryBlock
);
2259 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
2261 // Normal path: jump over the catch block.
2262 generator
.emitJump(catchEndLabel
.get());
2264 // Uncaught exception path: the catch block.
2265 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
2266 RefPtr
<RegisterID
> exceptionRegister
= generator
.popTryAndEmitCatch(tryData
, generator
.newTemporary(), here
.get());
2268 if (m_finallyBlock
) {
2269 // If the catch block throws an exception and we have a finally block, then the finally
2270 // block should "catch" that exception.
2271 tryData
= generator
.pushTry(here
.get());
2274 generator
.emitPushCatchScope(m_exceptionIdent
, exceptionRegister
.get(), DontDelete
);
2275 generator
.emitNode(dst
, m_catchBlock
);
2276 generator
.emitPopScope();
2277 generator
.emitLabel(catchEndLabel
.get());
2280 if (m_finallyBlock
) {
2281 RefPtr
<Label
> preFinallyLabel
= generator
.emitLabel(generator
.newLabel().get());
2283 generator
.popFinallyContext();
2285 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
2287 // Normal path: run the finally code, and jump to the end.
2288 generator
.emitNode(dst
, m_finallyBlock
);
2289 generator
.emitJump(finallyEndLabel
.get());
2291 // Uncaught exception path: invoke the finally block, then re-throw the exception.
2292 RefPtr
<RegisterID
> tempExceptionRegister
= generator
.popTryAndEmitCatch(tryData
, generator
.newTemporary(), preFinallyLabel
.get());
2293 generator
.emitNode(dst
, m_finallyBlock
);
2294 generator
.emitThrow(tempExceptionRegister
.get());
2296 generator
.emitLabel(finallyEndLabel
.get());
2300 // ------------------------------ ScopeNode -----------------------------
2302 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2306 m_statements
->emitBytecode(generator
, dst
);
2309 // ------------------------------ ProgramNode -----------------------------
2311 void ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2313 generator
.emitDebugHook(WillExecuteProgram
, startLine(), startStartOffset(), startLineStartOffset());
2315 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
2316 generator
.emitLoad(dstRegister
.get(), jsUndefined());
2317 emitStatementsBytecode(generator
, dstRegister
.get());
2319 generator
.emitDebugHook(DidExecuteProgram
, lastLine(), startOffset(), lineStartOffset());
2320 generator
.emitEnd(dstRegister
.get());
2323 // ------------------------------ EvalNode -----------------------------
2325 void EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2327 generator
.emitDebugHook(WillExecuteProgram
, startLine(), startStartOffset(), startLineStartOffset());
2329 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
2330 generator
.emitLoad(dstRegister
.get(), jsUndefined());
2331 emitStatementsBytecode(generator
, dstRegister
.get());
2333 generator
.emitDebugHook(DidExecuteProgram
, lastLine(), startOffset(), lineStartOffset());
2334 generator
.emitEnd(dstRegister
.get());
2337 // ------------------------------ FunctionBodyNode -----------------------------
2339 void FunctionBodyNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2341 generator
.emitDebugHook(DidEnterCallFrame
, startLine(), startStartOffset(), startLineStartOffset());
2342 emitStatementsBytecode(generator
, generator
.ignoredResult());
2344 StatementNode
* singleStatement
= this->singleStatement();
2345 ReturnNode
* returnNode
= 0;
2347 // Check for a return statement at the end of a function composed of a single block.
2348 if (singleStatement
&& singleStatement
->isBlock()) {
2349 StatementNode
* lastStatementInBlock
= static_cast<BlockNode
*>(singleStatement
)->lastStatement();
2350 if (lastStatementInBlock
&& lastStatementInBlock
->isReturnNode())
2351 returnNode
= static_cast<ReturnNode
*>(lastStatementInBlock
);
2354 // If there is no return we must automatically insert one.
2356 RegisterID
* r0
= generator
.isConstructor() ? generator
.thisRegister() : generator
.emitLoad(0, jsUndefined());
2357 ASSERT(startOffset() >= lineStartOffset());
2358 generator
.emitDebugHook(WillLeaveCallFrame
, lastLine(), startOffset(), lineStartOffset());
2359 generator
.emitReturn(r0
);
2363 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
2364 if (static_cast<BlockNode
*>(singleStatement
)->singleStatement()) {
2365 ExpressionNode
* returnValueExpression
= returnNode
->value();
2366 if (returnValueExpression
&& returnValueExpression
->isSubtract()) {
2367 ExpressionNode
* lhsExpression
= static_cast<SubNode
*>(returnValueExpression
)->lhs();
2368 ExpressionNode
* rhsExpression
= static_cast<SubNode
*>(returnValueExpression
)->rhs();
2369 if (lhsExpression
->isResolveNode()
2370 && rhsExpression
->isResolveNode()
2371 && generator
.isArgumentNumber(static_cast<ResolveNode
*>(lhsExpression
)->identifier(), 0)
2372 && generator
.isArgumentNumber(static_cast<ResolveNode
*>(rhsExpression
)->identifier(), 1)) {
2374 generator
.setIsNumericCompareFunction(true);
2380 // ------------------------------ FuncDeclNode ---------------------------------
2382 void FuncDeclNode::emitBytecode(BytecodeGenerator
&, RegisterID
*)
2386 // ------------------------------ FuncExprNode ---------------------------------
2388 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2390 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);
2393 // ------------------------------ DeconstructingAssignmentNode -----------------
2394 RegisterID
* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2396 if (RegisterID
* result
= m_bindings
->emitDirectBinding(generator
, dst
, m_initializer
))
2398 RefPtr
<RegisterID
> initializer
= generator
.tempDestination(dst
);
2399 generator
.emitNode(initializer
.get(), m_initializer
);
2400 m_bindings
->bindValue(generator
, initializer
.get());
2401 return generator
.moveToDestinationIfNeeded(dst
, initializer
.get());
2404 DeconstructionPatternNode::~DeconstructionPatternNode()
2408 void ArrayPatternNode::bindValue(BytecodeGenerator
& generator
, RegisterID
* rhs
) const
2410 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2411 auto target
= m_targetPatterns
[i
];
2414 RefPtr
<RegisterID
> temp
= generator
.newTemporary();
2415 generator
.emitLoad(temp
.get(), jsNumber(i
));
2416 generator
.emitGetByVal(temp
.get(), rhs
, temp
.get());
2417 target
->bindValue(generator
, temp
.get());
2421 RegisterID
* ArrayPatternNode::emitDirectBinding(BytecodeGenerator
& generator
, RegisterID
* dst
, ExpressionNode
* rhs
)
2423 if (rhs
->isResolveNode()
2424 && generator
.willResolveToArguments(static_cast<ResolveNode
*>(rhs
)->identifier())
2425 && !generator
.symbolTable().slowArguments()) {
2426 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2427 auto target
= m_targetPatterns
[i
];
2431 RefPtr
<RegisterID
> temp
= generator
.newTemporary();
2432 generator
.emitLoad(temp
.get(), jsNumber(i
));
2433 generator
.emitGetArgumentByVal(temp
.get(), generator
.uncheckedRegisterForArguments(), temp
.get());
2434 target
->bindValue(generator
, temp
.get());
2436 if (dst
== generator
.ignoredResult() || !dst
)
2437 return generator
.emitLoad(generator
.finalDestination(dst
), jsUndefined());
2438 Local local
= generator
.local(generator
.vm()->propertyNames
->arguments
);
2439 return generator
.moveToDestinationIfNeeded(dst
, local
.get());
2441 if (!rhs
->isSimpleArray())
2444 RefPtr
<RegisterID
> resultRegister
;
2445 if (dst
&& dst
!= generator
.ignoredResult())
2446 resultRegister
= generator
.emitNewArray(generator
.newTemporary(), 0, 0);
2447 ElementNode
* elementNodes
= static_cast<ArrayNode
*>(rhs
)->elements();
2448 Vector
<ExpressionNode
*> elements
;
2449 for (; elementNodes
; elementNodes
= elementNodes
->next())
2450 elements
.append(elementNodes
->value());
2451 if (m_targetPatterns
.size() != elements
.size())
2453 Vector
<RefPtr
<RegisterID
>> registers
;
2454 registers
.reserveCapacity(m_targetPatterns
.size());
2455 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2456 registers
.uncheckedAppend(generator
.newTemporary());
2457 generator
.emitNode(registers
.last().get(), elements
[i
]);
2459 generator
.emitPutByIndex(resultRegister
.get(), i
, registers
.last().get());
2462 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2463 if (m_targetPatterns
[i
])
2464 m_targetPatterns
[i
]->bindValue(generator
, registers
[i
].get());
2467 return generator
.moveToDestinationIfNeeded(dst
, resultRegister
.get());
2468 return generator
.emitLoad(generator
.finalDestination(dst
), jsUndefined());
2471 void ArrayPatternNode::toString(StringBuilder
& builder
) const
2473 builder
.append('[');
2474 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2475 if (!m_targetPatterns
[i
]) {
2476 builder
.append(',');
2479 m_targetPatterns
[i
]->toString(builder
);
2480 if (i
< m_targetPatterns
.size() - 1)
2481 builder
.append(',');
2483 builder
.append(']');
2486 void ArrayPatternNode::collectBoundIdentifiers(Vector
<Identifier
>& identifiers
) const
2488 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2489 if (DeconstructionPatternNode
* node
= m_targetPatterns
[i
].get())
2490 node
->collectBoundIdentifiers(identifiers
);
2494 void ObjectPatternNode::toString(StringBuilder
& builder
) const
2496 builder
.append('{');
2497 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2498 if (m_targetPatterns
[i
].wasString
) {
2499 builder
.append('"');
2500 escapeStringToBuilder(builder
, m_targetPatterns
[i
].propertyName
.string());
2501 builder
.append('"');
2503 builder
.append(m_targetPatterns
[i
].propertyName
.string());
2504 builder
.append(":");
2505 m_targetPatterns
[i
].pattern
->toString(builder
);
2506 if (i
< m_targetPatterns
.size() - 1)
2507 builder
.append(',');
2509 builder
.append('}');
2512 void ObjectPatternNode::bindValue(BytecodeGenerator
& generator
, RegisterID
* rhs
) const
2514 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
2515 auto& target
= m_targetPatterns
[i
];
2516 RefPtr
<RegisterID
> temp
= generator
.newTemporary();
2517 generator
.emitGetById(temp
.get(), rhs
, target
.propertyName
);
2518 target
.pattern
->bindValue(generator
, temp
.get());
2522 void ObjectPatternNode::collectBoundIdentifiers(Vector
<Identifier
>& identifiers
) const
2524 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++)
2525 m_targetPatterns
[i
].pattern
->collectBoundIdentifiers(identifiers
);
2528 void BindingNode::bindValue(BytecodeGenerator
& generator
, RegisterID
* value
) const
2530 if (Local local
= generator
.local(m_boundProperty
)) {
2531 if (local
.isReadOnly()) {
2532 generator
.emitReadOnlyExceptionIfNeeded();
2535 generator
.emitMove(local
.get(), value
);
2538 if (generator
.isStrictMode())
2539 generator
.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
2540 RegisterID
* scope
= generator
.emitResolveScope(generator
.newTemporary(), m_boundProperty
);
2541 generator
.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
2542 generator
.emitPutToScope(scope
, m_boundProperty
, value
, generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
2546 void BindingNode::toString(StringBuilder
& builder
) const
2548 builder
.append(m_boundProperty
.string());
2551 void BindingNode::collectBoundIdentifiers(Vector
<Identifier
>& identifiers
) const
2553 identifiers
.append(m_boundProperty
);
2556 RegisterID
* SpreadExpressionNode::emitBytecode(BytecodeGenerator
&, RegisterID
*)
2558 RELEASE_ASSERT_NOT_REACHED();