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, 2015 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"
43 #include "JSTemplateRegistryKey.h"
45 #include "PropertyNameArray.h"
46 #include "RegExpCache.h"
47 #include "RegExpObject.h"
48 #include "SamplingTool.h"
49 #include "StackAlignment.h"
50 #include "TemplateRegistryKey.h"
51 #include <wtf/Assertions.h>
52 #include <wtf/RefCountedLeakCounter.h>
53 #include <wtf/Threading.h>
60 Details of the emitBytecode function.
62 Return value: The register holding the production's value.
63 dst: An optional parameter specifying the most efficient destination at
64 which to store the production's value. The callee must honor dst.
66 The dst argument provides for a crude form of copy propagation. For example,
79 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
82 void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
84 RegisterID
* result
= generator
.emitNode(this);
85 if (fallThroughMode
== FallThroughMeansTrue
)
86 generator
.emitJumpIfFalse(result
, falseTarget
);
88 generator
.emitJumpIfTrue(result
, trueTarget
);
91 // ------------------------------ ThrowableExpressionData --------------------------------
93 RegisterID
* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator
& generator
, const String
& message
)
95 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
96 generator
.emitThrowReferenceError(message
);
97 return generator
.newTemporary();
100 // ------------------------------ ConstantNode ----------------------------------
102 void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
104 TriState value
= jsValue(generator
).pureToBoolean();
105 if (value
== MixedTriState
)
106 ExpressionNode::emitBytecodeInConditionContext(generator
, trueTarget
, falseTarget
, fallThroughMode
);
107 else if (value
== TrueTriState
&& fallThroughMode
== FallThroughMeansFalse
)
108 generator
.emitJump(trueTarget
);
109 else if (value
== FalseTriState
&& fallThroughMode
== FallThroughMeansTrue
)
110 generator
.emitJump(falseTarget
);
112 // All other cases are unconditional fall-throughs, like "if (true)".
115 RegisterID
* ConstantNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
117 if (dst
== generator
.ignoredResult())
119 return generator
.emitLoad(dst
, jsValue(generator
));
122 JSValue
StringNode::jsValue(BytecodeGenerator
& generator
) const
124 return generator
.addStringConstant(m_value
);
127 // ------------------------------ NumberNode ----------------------------------
129 RegisterID
* NumberNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
131 if (dst
== generator
.ignoredResult())
133 return generator
.emitLoad(dst
, jsValue(generator
), isIntegerNode() ? SourceCodeRepresentation::Integer
: SourceCodeRepresentation::Double
);
136 // ------------------------------ RegExpNode -----------------------------------
138 RegisterID
* RegExpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
140 if (dst
== generator
.ignoredResult())
142 return generator
.emitNewRegExp(generator
.finalDestination(dst
), RegExp::create(*generator
.vm(), m_pattern
.string(), regExpFlags(m_flags
.string())));
145 // ------------------------------ ThisNode -------------------------------------
147 RegisterID
* ThisNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
149 if (m_shouldAlwaysEmitTDZCheck
|| generator
.constructorKind() == ConstructorKind::Derived
)
150 generator
.emitTDZCheck(generator
.thisRegister());
152 if (dst
== generator
.ignoredResult())
155 RegisterID
* result
= generator
.moveToDestinationIfNeeded(dst
, generator
.thisRegister());
156 if (generator
.vm()->typeProfiler()) {
157 generator
.emitProfileType(generator
.thisRegister(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
158 static const unsigned thisLength
= 4;
159 generator
.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset
+ thisLength
, -1));
164 // ------------------------------ SuperNode -------------------------------------
166 RegisterID
* SuperNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
168 if (dst
== generator
.ignoredResult())
172 callee
.setIndex(JSStack::Callee
);
174 RefPtr
<RegisterID
> homeObject
= generator
.emitGetById(generator
.newTemporary(), &callee
, generator
.propertyNames().homeObjectPrivateName
);
175 RefPtr
<RegisterID
> protoParent
= generator
.emitGetById(generator
.newTemporary(), homeObject
.get(), generator
.propertyNames().underscoreProto
);
176 return generator
.emitGetById(generator
.finalDestination(dst
), protoParent
.get(), generator
.propertyNames().constructor
);
179 static RegisterID
* emitSuperBaseForCallee(BytecodeGenerator
& generator
)
182 callee
.setIndex(JSStack::Callee
);
184 RefPtr
<RegisterID
> homeObject
= generator
.emitGetById(generator
.newTemporary(), &callee
, generator
.propertyNames().homeObjectPrivateName
);
185 return generator
.emitGetById(generator
.newTemporary(), homeObject
.get(), generator
.propertyNames().underscoreProto
);
188 // ------------------------------ ResolveNode ----------------------------------
190 bool ResolveNode::isPure(BytecodeGenerator
& generator
) const
192 return generator
.variable(m_ident
).offset().isStack();
195 RegisterID
* ResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
197 Variable var
= generator
.variable(m_ident
);
198 if (RegisterID
* local
= var
.local()) {
199 if (dst
== generator
.ignoredResult())
201 if (generator
.vm()->typeProfiler()) {
202 generator
.emitProfileType(local
, ProfileTypeBytecodeHasGlobalID
, nullptr);
203 generator
.emitTypeProfilerExpressionInfo(m_position
, JSTextPosition(-1, m_position
.offset
+ m_ident
.length(), -1));
205 return generator
.moveToDestinationIfNeeded(dst
, local
);
208 JSTextPosition divot
= m_start
+ m_ident
.length();
209 generator
.emitExpressionInfo(divot
, m_start
, divot
);
210 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(dst
, var
);
211 RegisterID
* finalDest
= generator
.finalDestination(dst
);
212 RegisterID
* result
= generator
.emitGetFromScope(finalDest
, scope
.get(), var
, ThrowIfNotFound
);
213 if (generator
.vm()->typeProfiler()) {
214 generator
.emitProfileType(finalDest
, var
.isResolved() ? ProfileTypeBytecodeGetFromLocalScope
: ProfileTypeBytecodeGetFromScope
, &m_ident
);
215 generator
.emitTypeProfilerExpressionInfo(m_position
, JSTextPosition(-1, m_position
.offset
+ m_ident
.length(), -1));
220 #if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
221 // ------------------------------ TemplateStringNode -----------------------------------
223 RegisterID
* TemplateStringNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
225 if (dst
== generator
.ignoredResult())
227 return generator
.emitLoad(dst
, JSValue(generator
.addStringConstant(cooked())));
230 // ------------------------------ TemplateLiteralNode -----------------------------------
232 RegisterID
* TemplateLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
234 if (!m_templateExpressions
) {
235 TemplateStringNode
* templateString
= m_templateStrings
->value();
236 ASSERT_WITH_MESSAGE(!m_templateStrings
->next(), "Only one template element exists because there's no expression in a given template literal.");
237 return generator
.emitNode(dst
, templateString
);
240 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
242 TemplateStringListNode
* templateString
= m_templateStrings
;
243 TemplateExpressionListNode
* templateExpression
= m_templateExpressions
;
244 for (; templateExpression
; templateExpression
= templateExpression
->next(), templateString
= templateString
->next()) {
245 // Evaluate TemplateString.
246 if (!templateString
->value()->cooked().isEmpty()) {
247 temporaryRegisters
.append(generator
.newTemporary());
248 generator
.emitNode(temporaryRegisters
.last().get(), templateString
->value());
251 // Evaluate Expression.
252 temporaryRegisters
.append(generator
.newTemporary());
253 generator
.emitNode(temporaryRegisters
.last().get(), templateExpression
->value());
254 generator
.emitToString(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
257 // Evaluate tail TemplateString.
258 if (!templateString
->value()->cooked().isEmpty()) {
259 temporaryRegisters
.append(generator
.newTemporary());
260 generator
.emitNode(temporaryRegisters
.last().get(), templateString
->value());
263 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
266 // ------------------------------ TaggedTemplateNode -----------------------------------
268 RegisterID
* TaggedTemplateNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
270 ExpectedFunction expectedFunction
= NoExpectedFunction
;
271 RefPtr
<RegisterID
> tag
= nullptr;
272 RefPtr
<RegisterID
> base
= nullptr;
273 if (!m_tag
->isLocation()) {
274 tag
= generator
.newTemporary();
275 tag
= generator
.emitNode(tag
.get(), m_tag
);
276 } else if (m_tag
->isResolveNode()) {
277 ResolveNode
* resolve
= static_cast<ResolveNode
*>(m_tag
);
278 const Identifier
& identifier
= resolve
->identifier();
279 expectedFunction
= generator
.expectedFunctionForIdentifier(identifier
);
281 Variable var
= generator
.variable(identifier
);
282 if (RegisterID
* local
= var
.local())
283 tag
= generator
.emitMove(generator
.newTemporary(), local
);
285 tag
= generator
.newTemporary();
286 base
= generator
.newTemporary();
288 JSTextPosition newDivot
= divotStart() + identifier
.length();
289 generator
.emitExpressionInfo(newDivot
, divotStart(), newDivot
);
290 generator
.moveToDestinationIfNeeded(base
.get(), generator
.emitResolveScope(base
.get(), var
));
291 generator
.emitGetFromScope(tag
.get(), base
.get(), var
, ThrowIfNotFound
);
293 } else if (m_tag
->isBracketAccessorNode()) {
294 BracketAccessorNode
* bracket
= static_cast<BracketAccessorNode
*>(m_tag
);
295 base
= generator
.newTemporary();
296 base
= generator
.emitNode(base
.get(), bracket
->base());
297 RefPtr
<RegisterID
> property
= generator
.emitNode(bracket
->subscript());
298 tag
= generator
.emitGetByVal(generator
.newTemporary(), base
.get(), property
.get());
300 ASSERT(m_tag
->isDotAccessorNode());
301 DotAccessorNode
* dot
= static_cast<DotAccessorNode
*>(m_tag
);
302 base
= generator
.newTemporary();
303 base
= generator
.emitNode(base
.get(), dot
->base());
304 tag
= generator
.emitGetById(generator
.newTemporary(), base
.get(), dot
->identifier());
307 RefPtr
<RegisterID
> templateObject
= generator
.emitGetTemplateObject(generator
.newTemporary(), this);
309 unsigned expressionsCount
= 0;
310 for (TemplateExpressionListNode
* templateExpression
= m_templateLiteral
->templateExpressions(); templateExpression
; templateExpression
= templateExpression
->next())
313 CallArguments
callArguments(generator
, nullptr, 1 + expressionsCount
);
315 generator
.emitMove(callArguments
.thisRegister(), base
.get());
317 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
319 unsigned argumentIndex
= 0;
320 generator
.emitMove(callArguments
.argumentRegister(argumentIndex
++), templateObject
.get());
321 for (TemplateExpressionListNode
* templateExpression
= m_templateLiteral
->templateExpressions(); templateExpression
; templateExpression
= templateExpression
->next())
322 generator
.emitNode(callArguments
.argumentRegister(argumentIndex
++), templateExpression
->value());
324 return generator
.emitCall(generator
.finalDestination(dst
, tag
.get()), tag
.get(), expectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
328 // ------------------------------ ArrayNode ------------------------------------
330 RegisterID
* ArrayNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
332 // FIXME: Should we put all of this code into emitNewArray?
335 ElementNode
* firstPutElement
;
336 for (firstPutElement
= m_element
; firstPutElement
; firstPutElement
= firstPutElement
->next()) {
337 if (firstPutElement
->elision() || firstPutElement
->value()->isSpreadExpression())
342 if (!firstPutElement
&& !m_elision
)
343 return generator
.emitNewArray(generator
.finalDestination(dst
), m_element
, length
);
345 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.tempDestination(dst
), m_element
, length
);
346 ElementNode
* n
= firstPutElement
;
347 for (; n
; n
= n
->next()) {
348 if (n
->value()->isSpreadExpression())
350 RegisterID
* value
= generator
.emitNode(n
->value());
351 length
+= n
->elision();
352 generator
.emitPutByIndex(array
.get(), length
++, value
);
356 RegisterID
* value
= generator
.emitLoad(0, jsNumber(m_elision
+ length
));
357 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, value
);
360 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
363 RefPtr
<RegisterID
> index
= generator
.emitLoad(generator
.newTemporary(), jsNumber(length
));
364 auto spreader
= [this, array
, index
](BytecodeGenerator
& generator
, RegisterID
* value
)
366 generator
.emitDirectPutByVal(array
.get(), index
.get(), value
);
367 generator
.emitInc(index
.get());
369 for (; n
; n
= n
->next()) {
371 generator
.emitBinaryOp(op_add
, index
.get(), index
.get(), generator
.emitLoad(0, jsNumber(n
->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
372 if (n
->value()->isSpreadExpression()) {
373 SpreadExpressionNode
* spread
= static_cast<SpreadExpressionNode
*>(n
->value());
374 generator
.emitEnumeration(spread
, spread
->expression(), spreader
);
376 generator
.emitDirectPutByVal(array
.get(), index
.get(), generator
.emitNode(n
->value()));
377 generator
.emitInc(index
.get());
382 generator
.emitBinaryOp(op_add
, index
.get(), index
.get(), generator
.emitLoad(0, jsNumber(m_elision
)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
383 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, index
.get());
385 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
388 bool ArrayNode::isSimpleArray() const
390 if (m_elision
|| m_optional
)
392 for (ElementNode
* ptr
= m_element
; ptr
; ptr
= ptr
->next()) {
399 ArgumentListNode
* ArrayNode::toArgumentList(ParserArena
& parserArena
, int lineNumber
, int startPosition
) const
401 ASSERT(!m_elision
&& !m_optional
);
402 ElementNode
* ptr
= m_element
;
405 JSTokenLocation location
;
406 location
.line
= lineNumber
;
407 location
.startOffset
= startPosition
;
408 ArgumentListNode
* head
= new (parserArena
) ArgumentListNode(location
, ptr
->value());
409 ArgumentListNode
* tail
= head
;
411 for (; ptr
; ptr
= ptr
->next()) {
412 ASSERT(!ptr
->elision());
413 tail
= new (parserArena
) ArgumentListNode(location
, tail
, ptr
->value());
418 // ------------------------------ ObjectLiteralNode ----------------------------
420 RegisterID
* ObjectLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
423 if (dst
== generator
.ignoredResult())
425 return generator
.emitNewObject(generator
.finalDestination(dst
));
427 RefPtr
<RegisterID
> newObj
= generator
.emitNewObject(generator
.tempDestination(dst
));
428 generator
.emitNode(newObj
.get(), m_list
);
429 return generator
.moveToDestinationIfNeeded(dst
, newObj
.get());
432 // ------------------------------ PropertyListNode -----------------------------
434 static inline void emitPutHomeObject(BytecodeGenerator
& generator
, RegisterID
* function
, RegisterID
* homeObject
)
436 generator
.emitPutById(function
, generator
.propertyNames().homeObjectPrivateName
, homeObject
);
439 RegisterID
* PropertyListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
441 // Fast case: this loop just handles regular value properties.
442 PropertyListNode
* p
= this;
443 for (; p
&& (p
->m_node
->m_type
& PropertyNode::Constant
); p
= p
->m_next
)
444 emitPutConstantProperty(generator
, dst
, *p
->m_node
);
446 // Were there any get/set properties?
448 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
449 // a computed property, just emit everything as that may override previous values.
450 bool hasComputedProperty
= false;
452 typedef std::pair
<PropertyNode
*, PropertyNode
*> GetterSetterPair
;
453 typedef HashMap
<UniquedStringImpl
*, GetterSetterPair
, IdentifierRepHash
> GetterSetterMap
;
456 // Build a map, pairing get/set values together.
457 for (PropertyListNode
* q
= p
; q
; q
= q
->m_next
) {
458 PropertyNode
* node
= q
->m_node
;
459 if (node
->m_type
& PropertyNode::Computed
) {
460 hasComputedProperty
= true;
463 if (node
->m_type
& PropertyNode::Constant
)
466 // Duplicates are possible.
467 GetterSetterPair
pair(node
, static_cast<PropertyNode
*>(nullptr));
468 GetterSetterMap::AddResult result
= map
.add(node
->name()->impl(), pair
);
469 if (!result
.isNewEntry
) {
470 if (result
.iterator
->value
.first
->m_type
== node
->m_type
)
471 result
.iterator
->value
.first
= node
;
473 result
.iterator
->value
.second
= node
;
477 // Iterate over the remaining properties in the list.
478 for (; p
; p
= p
->m_next
) {
479 PropertyNode
* node
= p
->m_node
;
481 // Handle regular values.
482 if (node
->m_type
& PropertyNode::Constant
) {
483 emitPutConstantProperty(generator
, dst
, *node
);
487 RegisterID
* value
= generator
.emitNode(node
->m_assign
);
488 bool isClassProperty
= node
->needsSuperBinding();
490 emitPutHomeObject(generator
, value
, dst
);
492 ASSERT(node
->m_type
& (PropertyNode::Getter
| PropertyNode::Setter
));
494 // This is a get/set property which may be overridden by a computed property later.
495 if (hasComputedProperty
) {
496 if (node
->m_type
& PropertyNode::Getter
)
497 generator
.emitPutGetterById(dst
, *node
->name(), value
);
499 generator
.emitPutSetterById(dst
, *node
->name(), value
);
503 // This is a get/set property pair.
504 GetterSetterMap::iterator it
= map
.find(node
->name()->impl());
505 ASSERT(it
!= map
.end());
506 GetterSetterPair
& pair
= it
->value
;
508 // Was this already generated as a part of its partner?
509 if (pair
.second
== node
)
512 // Generate the paired node now.
513 RefPtr
<RegisterID
> getterReg
;
514 RefPtr
<RegisterID
> setterReg
;
515 RegisterID
* secondReg
= nullptr;
517 if (node
->m_type
& PropertyNode::Getter
) {
520 ASSERT(pair
.second
->m_type
& PropertyNode::Setter
);
521 setterReg
= generator
.emitNode(pair
.second
->m_assign
);
522 secondReg
= setterReg
.get();
524 setterReg
= generator
.newTemporary();
525 generator
.emitLoad(setterReg
.get(), jsUndefined());
528 ASSERT(node
->m_type
& PropertyNode::Setter
);
531 ASSERT(pair
.second
->m_type
& PropertyNode::Getter
);
532 getterReg
= generator
.emitNode(pair
.second
->m_assign
);
533 secondReg
= getterReg
.get();
535 getterReg
= generator
.newTemporary();
536 generator
.emitLoad(getterReg
.get(), jsUndefined());
540 ASSERT(!pair
.second
|| isClassProperty
== pair
.second
->needsSuperBinding());
541 if (isClassProperty
&& pair
.second
)
542 emitPutHomeObject(generator
, secondReg
, dst
);
544 if (isClassProperty
) {
545 RefPtr
<RegisterID
> propertyNameRegister
= generator
.emitLoad(generator
.newTemporary(), *node
->name());
546 generator
.emitCallDefineProperty(dst
, propertyNameRegister
.get(),
547 nullptr, getterReg
.get(), setterReg
.get(), BytecodeGenerator::PropertyConfigurable
, m_position
);
549 generator
.emitPutGetterSetter(dst
, *node
->name(), getterReg
.get(), setterReg
.get());
556 void PropertyListNode::emitPutConstantProperty(BytecodeGenerator
& generator
, RegisterID
* newObj
, PropertyNode
& node
)
558 RefPtr
<RegisterID
> value
= generator
.emitNode(node
.m_assign
);
559 if (node
.needsSuperBinding()) {
560 emitPutHomeObject(generator
, value
.get(), newObj
);
562 RefPtr
<RegisterID
> propertyNameRegister
;
564 propertyNameRegister
= generator
.emitLoad(generator
.newTemporary(), *node
.name());
566 propertyNameRegister
= generator
.emitNode(node
.m_expression
);
568 generator
.emitCallDefineProperty(newObj
, propertyNameRegister
.get(),
569 value
.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable
| BytecodeGenerator::PropertyWritable
, m_position
);
572 if (const auto* identifier
= node
.name()) {
573 Optional
<uint32_t> optionalIndex
= parseIndex(*identifier
);
574 if (!optionalIndex
) {
575 generator
.emitDirectPutById(newObj
, *identifier
, value
.get(), node
.putType());
579 RefPtr
<RegisterID
> index
= generator
.emitLoad(generator
.newTemporary(), jsNumber(optionalIndex
.value()));
580 generator
.emitDirectPutByVal(newObj
, index
.get(), value
.get());
583 RefPtr
<RegisterID
> propertyName
= generator
.emitNode(node
.m_expression
);
584 generator
.emitDirectPutByVal(newObj
, propertyName
.get(), value
.get());
587 // ------------------------------ BracketAccessorNode --------------------------------
589 RegisterID
* BracketAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
591 if (m_base
->isSuperNode()) {
592 // FIXME: Should we generate the profiler info?
593 if (m_subscript
->isString()) {
594 const Identifier
& id
= static_cast<StringNode
*>(m_subscript
)->value();
595 return generator
.emitGetById(generator
.finalDestination(dst
), emitSuperBaseForCallee(generator
), id
);
597 return generator
.emitGetByVal(generator
.finalDestination(dst
), emitSuperBaseForCallee(generator
), generator
.emitNode(m_subscript
));
601 RegisterID
* finalDest
= generator
.finalDestination(dst
);
603 if (m_subscript
->isString()) {
604 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
605 ret
= generator
.emitGetById(finalDest
, base
.get(), static_cast<StringNode
*>(m_subscript
)->value());
607 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
, m_subscript
->isPure(generator
));
608 RegisterID
* property
= generator
.emitNode(m_subscript
);
609 ret
= generator
.emitGetByVal(finalDest
, base
.get(), property
);
612 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
614 if (generator
.vm()->typeProfiler()) {
615 generator
.emitProfileType(finalDest
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
616 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
621 // ------------------------------ DotAccessorNode --------------------------------
623 RegisterID
* DotAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
625 RefPtr
<RegisterID
> base
= m_base
->isSuperNode() ? emitSuperBaseForCallee(generator
) : generator
.emitNode(m_base
);
626 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
627 RegisterID
* finalDest
= generator
.finalDestination(dst
);
628 RegisterID
* ret
= generator
.emitGetById(finalDest
, base
.get(), m_ident
);
629 if (generator
.vm()->typeProfiler()) {
630 generator
.emitProfileType(finalDest
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
631 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
636 // ------------------------------ ArgumentListNode -----------------------------
638 RegisterID
* ArgumentListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
641 return generator
.emitNode(dst
, m_expr
);
644 // ------------------------------ NewExprNode ----------------------------------
646 RegisterID
* NewExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
648 ExpectedFunction expectedFunction
;
649 if (m_expr
->isResolveNode())
650 expectedFunction
= generator
.expectedFunctionForIdentifier(static_cast<ResolveNode
*>(m_expr
)->identifier());
652 expectedFunction
= NoExpectedFunction
;
653 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
654 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
655 CallArguments
callArguments(generator
, m_args
);
656 generator
.emitMove(callArguments
.thisRegister(), func
.get());
657 return generator
.emitConstruct(returnValue
.get(), func
.get(), expectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
660 CallArguments::CallArguments(BytecodeGenerator
& generator
, ArgumentsNode
* argumentsNode
, unsigned additionalArguments
)
661 : m_argumentsNode(argumentsNode
)
664 if (generator
.shouldEmitProfileHooks())
665 m_profileHookRegister
= generator
.newTemporary();
667 size_t argumentCountIncludingThis
= 1 + additionalArguments
; // 'this' register.
669 for (ArgumentListNode
* node
= argumentsNode
->m_listNode
; node
; node
= node
->m_next
)
670 ++argumentCountIncludingThis
;
673 m_argv
.grow(argumentCountIncludingThis
);
674 for (int i
= argumentCountIncludingThis
- 1; i
>= 0; --i
) {
675 m_argv
[i
] = generator
.newTemporary();
676 ASSERT(static_cast<size_t>(i
) == m_argv
.size() - 1 || m_argv
[i
]->index() == m_argv
[i
+ 1]->index() - 1);
679 while (stackOffset() % stackAlignmentRegisters()) {
680 m_argv
.insert(0, generator
.newTemporary());
685 // ------------------------------ EvalFunctionCallNode ----------------------------------
687 RegisterID
* EvalFunctionCallNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
689 Variable var
= generator
.variable(generator
.propertyNames().eval
);
690 if (RegisterID
* local
= var
.local()) {
691 RefPtr
<RegisterID
> func
= generator
.emitMove(generator
.tempDestination(dst
), local
);
692 CallArguments
callArguments(generator
, m_args
);
693 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
694 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), callArguments
, divot(), divotStart(), divotEnd());
697 RefPtr
<RegisterID
> func
= generator
.newTemporary();
698 CallArguments
callArguments(generator
, m_args
);
699 JSTextPosition newDivot
= divotStart() + 4;
700 generator
.emitExpressionInfo(newDivot
, divotStart(), newDivot
);
701 generator
.moveToDestinationIfNeeded(
702 callArguments
.thisRegister(),
703 generator
.emitResolveScope(callArguments
.thisRegister(), var
));
704 generator
.emitGetFromScope(func
.get(), callArguments
.thisRegister(), var
, ThrowIfNotFound
);
705 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), callArguments
, divot(), divotStart(), divotEnd());
708 // ------------------------------ FunctionCallValueNode ----------------------------------
710 RegisterID
* FunctionCallValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
712 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
713 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
714 CallArguments
callArguments(generator
, m_args
);
715 if (m_expr
->isSuperNode()) {
716 ASSERT(generator
.isConstructor());
717 ASSERT(generator
.constructorKind() == ConstructorKind::Derived
);
718 generator
.emitMove(callArguments
.thisRegister(), generator
.newTarget());
719 RegisterID
* ret
= generator
.emitConstruct(returnValue
.get(), func
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
720 generator
.emitMove(generator
.thisRegister(), ret
);
723 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
724 RegisterID
* ret
= generator
.emitCall(returnValue
.get(), func
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
725 if (generator
.vm()->typeProfiler()) {
726 generator
.emitProfileType(returnValue
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
727 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
732 // ------------------------------ FunctionCallResolveNode ----------------------------------
734 RegisterID
* FunctionCallResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
736 ExpectedFunction expectedFunction
= generator
.expectedFunctionForIdentifier(m_ident
);
738 Variable var
= generator
.variable(m_ident
);
739 if (RegisterID
* local
= var
.local()) {
740 RefPtr
<RegisterID
> func
= generator
.emitMove(generator
.tempDestination(dst
), local
);
741 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
742 CallArguments
callArguments(generator
, m_args
);
743 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
744 // This passes NoExpectedFunction because we expect that if the function is in a
745 // local variable, then it's not one of our built-in constructors.
746 RegisterID
* ret
= generator
.emitCall(returnValue
.get(), func
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
747 if (generator
.vm()->typeProfiler()) {
748 generator
.emitProfileType(returnValue
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
749 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
754 RefPtr
<RegisterID
> func
= generator
.newTemporary();
755 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, func
.get());
756 CallArguments
callArguments(generator
, m_args
);
758 JSTextPosition newDivot
= divotStart() + m_ident
.length();
759 generator
.emitExpressionInfo(newDivot
, divotStart(), newDivot
);
760 generator
.moveToDestinationIfNeeded(
761 callArguments
.thisRegister(),
762 generator
.emitResolveScope(callArguments
.thisRegister(), var
));
763 generator
.emitGetFromScope(func
.get(), callArguments
.thisRegister(), var
, ThrowIfNotFound
);
764 RegisterID
* ret
= generator
.emitCall(returnValue
.get(), func
.get(), expectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
765 if (generator
.vm()->typeProfiler()) {
766 generator
.emitProfileType(returnValue
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
767 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
772 // ------------------------------ BytecodeIntrinsicNode ----------------------------------
774 RegisterID
* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
776 return (this->*m_emitter
)(generator
, dst
);
779 RegisterID
* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator
& generator
, RegisterID
* dst
)
781 ArgumentListNode
* node
= m_args
->m_listNode
;
782 RefPtr
<RegisterID
> base
= generator
.emitNode(node
);
784 RefPtr
<RegisterID
> index
= generator
.emitNode(node
);
786 RefPtr
<RegisterID
> value
= generator
.emitNode(node
);
788 ASSERT(!node
->m_next
);
790 return generator
.moveToDestinationIfNeeded(dst
, generator
.emitDirectPutByVal(base
.get(), index
.get(), value
.get()));
793 RegisterID
* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator
& generator
, RegisterID
* dst
)
795 ArgumentListNode
* node
= m_args
->m_listNode
;
796 RefPtr
<RegisterID
> src
= generator
.emitNode(node
);
797 ASSERT(!node
->m_next
);
799 return generator
.moveToDestinationIfNeeded(dst
, generator
.emitToString(generator
.tempDestination(dst
), src
.get()));
802 // ------------------------------ FunctionCallBracketNode ----------------------------------
804 RegisterID
* FunctionCallBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
806 bool baseIsSuper
= m_base
->isSuperNode();
807 bool subscriptIsString
= m_subscript
->isString();
809 RefPtr
<RegisterID
> base
;
811 base
= emitSuperBaseForCallee(generator
);
813 if (subscriptIsString
)
814 base
= generator
.emitNode(m_base
);
816 base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
, m_subscript
->isPure(generator
));
819 RefPtr
<RegisterID
> function
;
820 if (subscriptIsString
) {
821 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
822 function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), static_cast<StringNode
*>(m_subscript
)->value());
824 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
825 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
826 function
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
829 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, function
.get());
830 CallArguments
callArguments(generator
, m_args
);
832 generator
.emitMove(callArguments
.thisRegister(), generator
.thisRegister());
834 generator
.emitMove(callArguments
.thisRegister(), base
.get());
835 RegisterID
* ret
= generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
836 if (generator
.vm()->typeProfiler()) {
837 generator
.emitProfileType(returnValue
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
838 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
843 // ------------------------------ FunctionCallDotNode ----------------------------------
845 RegisterID
* FunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
847 RefPtr
<RegisterID
> function
= generator
.tempDestination(dst
);
848 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, function
.get());
849 CallArguments
callArguments(generator
, m_args
);
850 bool baseIsSuper
= m_base
->isSuperNode();
852 generator
.emitMove(callArguments
.thisRegister(), generator
.thisRegister());
854 generator
.emitNode(callArguments
.thisRegister(), m_base
);
855 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
856 generator
.emitGetById(function
.get(), baseIsSuper
? emitSuperBaseForCallee(generator
) : callArguments
.thisRegister(), m_ident
);
857 RegisterID
* ret
= generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
858 if (generator
.vm()->typeProfiler()) {
859 generator
.emitProfileType(returnValue
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
860 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
865 RegisterID
* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
867 RefPtr
<Label
> realCall
= generator
.newLabel();
868 RefPtr
<Label
> end
= generator
.newLabel();
869 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
870 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
871 RefPtr
<RegisterID
> function
;
872 bool emitCallCheck
= !generator
.isBuiltinFunction();
874 function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), generator
.propertyNames().builtinNames().callPublicName());
875 generator
.emitJumpIfNotFunctionCall(function
.get(), realCall
.get());
877 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
);
879 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
&& m_args
->m_listNode
->m_expr
->isSpreadExpression()) {
880 RefPtr
<RegisterID
> profileHookRegister
;
881 if (generator
.shouldEmitProfileHooks())
882 profileHookRegister
= generator
.newTemporary();
883 SpreadExpressionNode
* spread
= static_cast<SpreadExpressionNode
*>(m_args
->m_listNode
->m_expr
);
884 ExpressionNode
* subject
= spread
->expression();
885 RefPtr
<RegisterID
> argumentsRegister
;
886 argumentsRegister
= generator
.emitNode(subject
);
887 generator
.emitExpressionInfo(spread
->divot(), spread
->divotStart(), spread
->divotEnd());
888 RefPtr
<RegisterID
> thisRegister
= generator
.emitGetByVal(generator
.newTemporary(), argumentsRegister
.get(), generator
.emitLoad(0, jsNumber(0)));
889 generator
.emitCallVarargs(returnValue
.get(), base
.get(), thisRegister
.get(), argumentsRegister
.get(), generator
.newTemporary(), 1, profileHookRegister
.get(), divot(), divotStart(), divotEnd());
890 } else if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
891 ArgumentListNode
* oldList
= m_args
->m_listNode
;
892 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
894 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
895 CallArguments
callArguments(generator
, m_args
);
896 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
897 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
898 m_args
->m_listNode
= oldList
;
900 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
901 CallArguments
callArguments(generator
, m_args
);
902 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
903 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
907 generator
.emitJump(end
.get());
908 generator
.emitLabel(realCall
.get());
910 CallArguments
callArguments(generator
, m_args
);
911 generator
.emitMove(callArguments
.thisRegister(), base
.get());
912 generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
914 generator
.emitLabel(end
.get());
916 if (generator
.vm()->typeProfiler()) {
917 generator
.emitProfileType(returnValue
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
918 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
920 return returnValue
.get();
923 static bool areTrivialApplyArguments(ArgumentsNode
* args
)
925 return !args
->m_listNode
|| !args
->m_listNode
->m_expr
|| !args
->m_listNode
->m_next
926 || (!args
->m_listNode
->m_next
->m_next
&& args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
929 RegisterID
* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
931 // A few simple cases can be trivially handled as ordinary function calls.
932 // function.apply(), function.apply(arg) -> identical to function.call
933 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
934 bool mayBeCall
= areTrivialApplyArguments(m_args
);
936 RefPtr
<Label
> realCall
= generator
.newLabel();
937 RefPtr
<Label
> end
= generator
.newLabel();
938 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
939 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
940 RefPtr
<RegisterID
> function
;
941 RefPtr
<RegisterID
> returnValue
= generator
.finalDestination(dst
, function
.get());
942 bool emitCallCheck
= !generator
.isBuiltinFunction();
944 function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), generator
.propertyNames().builtinNames().applyPublicName());
945 generator
.emitJumpIfNotFunctionApply(function
.get(), realCall
.get());
948 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
949 ArgumentListNode
* oldList
= m_args
->m_listNode
;
950 if (m_args
->m_listNode
->m_expr
->isSpreadExpression()) {
951 SpreadExpressionNode
* spread
= static_cast<SpreadExpressionNode
*>(m_args
->m_listNode
->m_expr
);
952 RefPtr
<RegisterID
> profileHookRegister
;
953 if (generator
.shouldEmitProfileHooks())
954 profileHookRegister
= generator
.newTemporary();
955 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.newTemporary(), base
.get());
956 RefPtr
<RegisterID
> index
= generator
.emitLoad(generator
.newTemporary(), jsNumber(0));
957 RefPtr
<RegisterID
> thisRegister
= generator
.emitLoad(generator
.newTemporary(), jsUndefined());
958 RefPtr
<RegisterID
> argumentsRegister
= generator
.emitLoad(generator
.newTemporary(), jsUndefined());
960 auto extractor
= [&thisRegister
, &argumentsRegister
, &index
](BytecodeGenerator
& generator
, RegisterID
* value
)
962 RefPtr
<Label
> haveThis
= generator
.newLabel();
963 RefPtr
<Label
> end
= generator
.newLabel();
964 RefPtr
<RegisterID
> compareResult
= generator
.newTemporary();
965 RefPtr
<RegisterID
> indexZeroCompareResult
= generator
.emitBinaryOp(op_eq
, compareResult
.get(), index
.get(), generator
.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
966 generator
.emitJumpIfFalse(indexZeroCompareResult
.get(), haveThis
.get());
967 generator
.emitMove(thisRegister
.get(), value
);
968 generator
.emitLoad(index
.get(), jsNumber(1));
969 generator
.emitJump(end
.get());
970 generator
.emitLabel(haveThis
.get());
971 RefPtr
<RegisterID
> indexOneCompareResult
= generator
.emitBinaryOp(op_eq
, compareResult
.get(), index
.get(), generator
.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
972 generator
.emitJumpIfFalse(indexOneCompareResult
.get(), end
.get());
973 generator
.emitMove(argumentsRegister
.get(), value
);
974 generator
.emitLoad(index
.get(), jsNumber(2));
975 generator
.emitLabel(end
.get());
977 generator
.emitEnumeration(this, spread
->expression(), extractor
);
978 generator
.emitCallVarargs(returnValue
.get(), realFunction
.get(), thisRegister
.get(), argumentsRegister
.get(), generator
.newTemporary(), 0, profileHookRegister
.get(), divot(), divotStart(), divotEnd());
979 } else if (m_args
->m_listNode
->m_next
) {
980 ASSERT(m_args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
981 ASSERT(!m_args
->m_listNode
->m_next
->m_next
);
982 m_args
->m_listNode
= static_cast<ArrayNode
*>(m_args
->m_listNode
->m_next
->m_expr
)->toArgumentList(generator
.parserArena(), 0, 0);
983 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
984 CallArguments
callArguments(generator
, m_args
);
985 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
986 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
988 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
989 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
990 CallArguments
callArguments(generator
, m_args
);
991 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
992 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
994 m_args
->m_listNode
= oldList
;
996 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
997 CallArguments
callArguments(generator
, m_args
);
998 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
999 generator
.emitCall(returnValue
.get(), realFunction
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
1002 ASSERT(m_args
->m_listNode
&& m_args
->m_listNode
->m_next
);
1003 RefPtr
<RegisterID
> profileHookRegister
;
1004 if (generator
.shouldEmitProfileHooks())
1005 profileHookRegister
= generator
.newTemporary();
1006 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
1007 RefPtr
<RegisterID
> thisRegister
= generator
.emitNode(m_args
->m_listNode
->m_expr
);
1008 RefPtr
<RegisterID
> argsRegister
;
1009 ArgumentListNode
* args
= m_args
->m_listNode
->m_next
;
1010 argsRegister
= generator
.emitNode(args
->m_expr
);
1012 // Function.prototype.apply ignores extra arguments, but we still
1013 // need to evaluate them for side effects.
1014 while ((args
= args
->m_next
))
1015 generator
.emitNode(args
->m_expr
);
1017 generator
.emitCallVarargs(returnValue
.get(), realFunction
.get(), thisRegister
.get(), argsRegister
.get(), generator
.newTemporary(), 0, profileHookRegister
.get(), divot(), divotStart(), divotEnd());
1019 if (emitCallCheck
) {
1020 generator
.emitJump(end
.get());
1021 generator
.emitLabel(realCall
.get());
1022 CallArguments
callArguments(generator
, m_args
);
1023 generator
.emitMove(callArguments
.thisRegister(), base
.get());
1024 generator
.emitCall(returnValue
.get(), function
.get(), NoExpectedFunction
, callArguments
, divot(), divotStart(), divotEnd());
1025 generator
.emitLabel(end
.get());
1027 if (generator
.vm()->typeProfiler()) {
1028 generator
.emitProfileType(returnValue
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1029 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1031 return returnValue
.get();
1034 // ------------------------------ PostfixNode ----------------------------------
1036 static RegisterID
* emitIncOrDec(BytecodeGenerator
& generator
, RegisterID
* srcDst
, Operator oper
)
1038 return (oper
== OpPlusPlus
) ? generator
.emitInc(srcDst
) : generator
.emitDec(srcDst
);
1041 static RegisterID
* emitPostIncOrDec(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* srcDst
, Operator oper
)
1044 return generator
.emitToNumber(generator
.finalDestination(dst
), srcDst
);
1045 RefPtr
<RegisterID
> tmp
= generator
.emitToNumber(generator
.tempDestination(dst
), srcDst
);
1046 emitIncOrDec(generator
, srcDst
, oper
);
1047 return generator
.moveToDestinationIfNeeded(dst
, tmp
.get());
1050 RegisterID
* PostfixNode::emitResolve(BytecodeGenerator
& generator
, RegisterID
* dst
)
1052 if (dst
== generator
.ignoredResult())
1053 return PrefixNode::emitResolve(generator
, dst
);
1055 ASSERT(m_expr
->isResolveNode());
1056 ResolveNode
* resolve
= static_cast<ResolveNode
*>(m_expr
);
1057 const Identifier
& ident
= resolve
->identifier();
1059 Variable var
= generator
.variable(ident
);
1060 if (RegisterID
* local
= var
.local()) {
1061 RefPtr
<RegisterID
> localReg
= local
;
1062 if (var
.isReadOnly()) {
1063 generator
.emitReadOnlyExceptionIfNeeded();
1064 localReg
= generator
.emitMove(generator
.tempDestination(dst
), local
);
1065 } else if (generator
.vm()->typeProfiler()) {
1066 RefPtr
<RegisterID
> tempDst
= generator
.finalDestination(dst
);
1067 ASSERT(dst
!= localReg
);
1068 RefPtr
<RegisterID
> tempDstSrc
= generator
.newTemporary();
1069 generator
.emitToNumber(tempDst
.get(), localReg
.get());
1070 generator
.emitMove(tempDstSrc
.get(), localReg
.get());
1071 emitIncOrDec(generator
, tempDstSrc
.get(), m_operator
);
1072 generator
.emitMove(localReg
.get(), tempDstSrc
.get());
1073 if (generator
.vm()->typeProfiler())
1074 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1075 return tempDst
.get();
1077 return emitPostIncOrDec(generator
, generator
.finalDestination(dst
), localReg
.get(), m_operator
);
1080 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1081 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(nullptr, var
);
1082 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), var
, ThrowIfNotFound
);
1083 RefPtr
<RegisterID
> oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
1084 generator
.emitPutToScope(scope
.get(), var
, value
.get(), ThrowIfNotFound
);
1085 if (generator
.vm()->typeProfiler()) {
1086 generator
.emitProfileType(value
.get(), var
.isResolved() ? ProfileTypeBytecodePutToLocalScope
: ProfileTypeBytecodePutToScope
, &ident
);
1087 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1090 return oldValue
.get();
1093 RegisterID
* PostfixNode::emitBracket(BytecodeGenerator
& generator
, RegisterID
* dst
)
1095 if (dst
== generator
.ignoredResult())
1096 return PrefixNode::emitBracket(generator
, dst
);
1098 ASSERT(m_expr
->isBracketAccessorNode());
1099 BracketAccessorNode
* bracketAccessor
= static_cast<BracketAccessorNode
*>(m_expr
);
1100 ExpressionNode
* baseNode
= bracketAccessor
->base();
1101 ExpressionNode
* subscript
= bracketAccessor
->subscript();
1103 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(baseNode
, bracketAccessor
->subscriptHasAssignments(), subscript
->isPure(generator
));
1104 RefPtr
<RegisterID
> property
= generator
.emitNode(subscript
);
1106 generator
.emitExpressionInfo(bracketAccessor
->divot(), bracketAccessor
->divotStart(), bracketAccessor
->divotEnd());
1107 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.newTemporary(), base
.get(), property
.get());
1108 RegisterID
* oldValue
= emitPostIncOrDec(generator
, generator
.tempDestination(dst
), value
.get(), m_operator
);
1109 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1110 generator
.emitPutByVal(base
.get(), property
.get(), value
.get());
1111 if (generator
.vm()->typeProfiler()) {
1112 generator
.emitProfileType(value
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1113 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1115 return generator
.moveToDestinationIfNeeded(dst
, oldValue
);
1118 RegisterID
* PostfixNode::emitDot(BytecodeGenerator
& generator
, RegisterID
* dst
)
1120 if (dst
== generator
.ignoredResult())
1121 return PrefixNode::emitDot(generator
, dst
);
1123 ASSERT(m_expr
->isDotAccessorNode());
1124 DotAccessorNode
* dotAccessor
= static_cast<DotAccessorNode
*>(m_expr
);
1125 ExpressionNode
* baseNode
= dotAccessor
->base();
1126 const Identifier
& ident
= dotAccessor
->identifier();
1128 RefPtr
<RegisterID
> base
= generator
.emitNode(baseNode
);
1130 generator
.emitExpressionInfo(dotAccessor
->divot(), dotAccessor
->divotStart(), dotAccessor
->divotEnd());
1131 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.newTemporary(), base
.get(), ident
);
1132 RegisterID
* oldValue
= emitPostIncOrDec(generator
, generator
.tempDestination(dst
), value
.get(), m_operator
);
1133 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1134 generator
.emitPutById(base
.get(), ident
, value
.get());
1135 if (generator
.vm()->typeProfiler()) {
1136 generator
.emitProfileType(value
.get(), ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1137 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1139 return generator
.moveToDestinationIfNeeded(dst
, oldValue
);
1142 RegisterID
* PostfixNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1144 if (m_expr
->isResolveNode())
1145 return emitResolve(generator
, dst
);
1147 if (m_expr
->isBracketAccessorNode())
1148 return emitBracket(generator
, dst
);
1150 if (m_expr
->isDotAccessorNode())
1151 return emitDot(generator
, dst
);
1153 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
1154 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1155 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
1158 // ------------------------------ DeleteResolveNode -----------------------------------
1160 RegisterID
* DeleteResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1162 Variable var
= generator
.variable(m_ident
);
1164 return generator
.emitLoad(generator
.finalDestination(dst
), false);
1166 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1167 RefPtr
<RegisterID
> base
= generator
.emitResolveScope(dst
, var
);
1168 return generator
.emitDeleteById(generator
.finalDestination(dst
, base
.get()), base
.get(), m_ident
);
1171 // ------------------------------ DeleteBracketNode -----------------------------------
1173 RegisterID
* DeleteBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1175 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
1176 RefPtr
<RegisterID
> r1
= generator
.emitNode(m_subscript
);
1178 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1179 if (m_base
->isSuperNode())
1180 return emitThrowReferenceError(generator
, "Cannot delete a super property");
1181 return generator
.emitDeleteByVal(generator
.finalDestination(dst
), r0
.get(), r1
.get());
1184 // ------------------------------ DeleteDotNode -----------------------------------
1186 RegisterID
* DeleteDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1188 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
1190 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1191 if (m_base
->isSuperNode())
1192 return emitThrowReferenceError(generator
, "Cannot delete a super property");
1193 return generator
.emitDeleteById(generator
.finalDestination(dst
), r0
.get(), m_ident
);
1196 // ------------------------------ DeleteValueNode -----------------------------------
1198 RegisterID
* DeleteValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1200 generator
.emitNode(generator
.ignoredResult(), m_expr
);
1202 // delete on a non-location expression ignores the value and returns true
1203 return generator
.emitLoad(generator
.finalDestination(dst
), true);
1206 // ------------------------------ VoidNode -------------------------------------
1208 RegisterID
* VoidNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1210 if (dst
== generator
.ignoredResult()) {
1211 generator
.emitNode(generator
.ignoredResult(), m_expr
);
1214 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
1215 return generator
.emitLoad(dst
, jsUndefined());
1218 // ------------------------------ TypeOfResolveNode -----------------------------------
1220 RegisterID
* TypeOfResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1222 Variable var
= generator
.variable(m_ident
);
1223 if (RegisterID
* local
= var
.local()) {
1224 if (dst
== generator
.ignoredResult())
1226 return generator
.emitTypeOf(generator
.finalDestination(dst
), local
);
1229 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(dst
, var
);
1230 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), var
, DoNotThrowIfNotFound
);
1231 if (dst
== generator
.ignoredResult())
1233 return generator
.emitTypeOf(generator
.finalDestination(dst
, scope
.get()), value
.get());
1236 // ------------------------------ TypeOfValueNode -----------------------------------
1238 RegisterID
* TypeOfValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1240 if (dst
== generator
.ignoredResult()) {
1241 generator
.emitNode(generator
.ignoredResult(), m_expr
);
1244 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
1245 return generator
.emitTypeOf(generator
.finalDestination(dst
), src
.get());
1248 // ------------------------------ PrefixNode ----------------------------------
1250 RegisterID
* PrefixNode::emitResolve(BytecodeGenerator
& generator
, RegisterID
* dst
)
1252 ASSERT(m_expr
->isResolveNode());
1253 ResolveNode
* resolve
= static_cast<ResolveNode
*>(m_expr
);
1254 const Identifier
& ident
= resolve
->identifier();
1256 Variable var
= generator
.variable(ident
);
1257 if (RegisterID
* local
= var
.local()) {
1258 RefPtr
<RegisterID
> localReg
= local
;
1259 if (var
.isReadOnly()) {
1260 generator
.emitReadOnlyExceptionIfNeeded();
1261 localReg
= generator
.emitMove(generator
.tempDestination(dst
), localReg
.get());
1262 } else if (generator
.vm()->typeProfiler()) {
1263 RefPtr
<RegisterID
> tempDst
= generator
.tempDestination(dst
);
1264 generator
.emitMove(tempDst
.get(), localReg
.get());
1265 emitIncOrDec(generator
, tempDst
.get(), m_operator
);
1266 generator
.emitMove(localReg
.get(), tempDst
.get());
1267 if (generator
.vm()->typeProfiler())
1268 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1269 return generator
.moveToDestinationIfNeeded(dst
, tempDst
.get());
1271 emitIncOrDec(generator
, localReg
.get(), m_operator
);
1272 return generator
.moveToDestinationIfNeeded(dst
, localReg
.get());
1275 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1276 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(dst
, var
);
1277 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), var
, ThrowIfNotFound
);
1278 emitIncOrDec(generator
, value
.get(), m_operator
);
1279 generator
.emitPutToScope(scope
.get(), var
, value
.get(), ThrowIfNotFound
);
1280 if (generator
.vm()->typeProfiler()) {
1281 generator
.emitProfileType(value
.get(), var
.isResolved() ? ProfileTypeBytecodePutToLocalScope
: ProfileTypeBytecodePutToScope
, &ident
);
1282 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1284 return generator
.moveToDestinationIfNeeded(dst
, value
.get());
1287 RegisterID
* PrefixNode::emitBracket(BytecodeGenerator
& generator
, RegisterID
* dst
)
1289 ASSERT(m_expr
->isBracketAccessorNode());
1290 BracketAccessorNode
* bracketAccessor
= static_cast<BracketAccessorNode
*>(m_expr
);
1291 ExpressionNode
* baseNode
= bracketAccessor
->base();
1292 ExpressionNode
* subscript
= bracketAccessor
->subscript();
1294 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(baseNode
, bracketAccessor
->subscriptHasAssignments(), subscript
->isPure(generator
));
1295 RefPtr
<RegisterID
> property
= generator
.emitNode(subscript
);
1296 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
1298 generator
.emitExpressionInfo(bracketAccessor
->divot(), bracketAccessor
->divotStart(), bracketAccessor
->divotEnd());
1299 RegisterID
* value
= generator
.emitGetByVal(propDst
.get(), base
.get(), property
.get());
1300 emitIncOrDec(generator
, value
, m_operator
);
1301 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1302 generator
.emitPutByVal(base
.get(), property
.get(), value
);
1303 if (generator
.vm()->typeProfiler()) {
1304 generator
.emitProfileType(value
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1305 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1307 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
1310 RegisterID
* PrefixNode::emitDot(BytecodeGenerator
& generator
, RegisterID
* dst
)
1312 ASSERT(m_expr
->isDotAccessorNode());
1313 DotAccessorNode
* dotAccessor
= static_cast<DotAccessorNode
*>(m_expr
);
1314 ExpressionNode
* baseNode
= dotAccessor
->base();
1315 const Identifier
& ident
= dotAccessor
->identifier();
1317 RefPtr
<RegisterID
> base
= generator
.emitNode(baseNode
);
1318 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
1320 generator
.emitExpressionInfo(dotAccessor
->divot(), dotAccessor
->divotStart(), dotAccessor
->divotEnd());
1321 RegisterID
* value
= generator
.emitGetById(propDst
.get(), base
.get(), ident
);
1322 emitIncOrDec(generator
, value
, m_operator
);
1323 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1324 generator
.emitPutById(base
.get(), ident
, value
);
1325 if (generator
.vm()->typeProfiler()) {
1326 generator
.emitProfileType(value
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1327 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1329 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
1332 RegisterID
* PrefixNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1334 if (m_expr
->isResolveNode())
1335 return emitResolve(generator
, dst
);
1337 if (m_expr
->isBracketAccessorNode())
1338 return emitBracket(generator
, dst
);
1340 if (m_expr
->isDotAccessorNode())
1341 return emitDot(generator
, dst
);
1343 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
1344 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1345 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
1348 // ------------------------------ Unary Operation Nodes -----------------------------------
1350 RegisterID
* UnaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1352 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
1353 generator
.emitExpressionInfo(position(), position(), position());
1354 return generator
.emitUnaryOp(opcodeID(), generator
.finalDestination(dst
), src
.get());
1357 // ------------------------------ BitwiseNotNode -----------------------------------
1359 RegisterID
* BitwiseNotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1361 RefPtr
<RegisterID
> src2
= generator
.emitLoad(generator
.newTemporary(), jsNumber(-1));
1362 RefPtr
<RegisterID
> src1
= generator
.emitNode(m_expr
);
1363 return generator
.emitBinaryOp(op_bitxor
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), OperandTypes(m_expr
->resultDescriptor(), ResultType::numberTypeIsInt32()));
1366 // ------------------------------ LogicalNotNode -----------------------------------
1368 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1370 // reverse the true and false targets
1371 generator
.emitNodeInConditionContext(expr(), falseTarget
, trueTarget
, invert(fallThroughMode
));
1375 // ------------------------------ Binary Operation Nodes -----------------------------------
1377 // BinaryOpNode::emitStrcat:
1379 // This node generates an op_strcat operation. This opcode can handle concatenation of three or
1380 // more values, where we can determine a set of separate op_add operations would be operating on
1383 // This function expects to be operating on a graph of AST nodes looking something like this:
1393 // The assignment operation is optional, if it exists the register holding the value on the
1394 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
1396 // The method should be called on the node at the root of the tree of regular binary add
1397 // operations (marked in the diagram with a double set of parentheses). This node must
1398 // be performing a string concatenation (determined by statically detecting that at least
1399 // one child must be a string).
1401 // Since the minimum number of values being concatenated together is expected to be 3, if
1402 // a lhs to a concatenating assignment is not provided then the root add should have at
1403 // least one left child that is also an add that can be determined to be operating on strings.
1405 RegisterID
* BinaryOpNode::emitStrcat(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* lhs
, ReadModifyResolveNode
* emitExpressionInfoForMe
)
1408 ASSERT(resultDescriptor().definitelyIsString());
1410 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1411 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1412 // added first, and the leftmost child is never added, so the vector produced for the
1413 // example above will be [ c, b ].
1414 Vector
<ExpressionNode
*, 16> reverseExpressionList
;
1415 reverseExpressionList
.append(m_expr2
);
1417 // Examine the left child of the add. So long as this is a string add, add its right-child
1418 // to the list, and keep processing along the left fork.
1419 ExpressionNode
* leftMostAddChild
= m_expr1
;
1420 while (leftMostAddChild
->isAdd() && leftMostAddChild
->resultDescriptor().definitelyIsString()) {
1421 reverseExpressionList
.append(static_cast<AddNode
*>(leftMostAddChild
)->m_expr2
);
1422 leftMostAddChild
= static_cast<AddNode
*>(leftMostAddChild
)->m_expr1
;
1425 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
1427 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1428 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1429 // op_strcat node handle its conversion if required).
1431 temporaryRegisters
.append(generator
.newTemporary());
1433 // Emit code for the leftmost node ((a) in the example).
1434 temporaryRegisters
.append(generator
.newTemporary());
1435 RegisterID
* leftMostAddChildTempRegister
= temporaryRegisters
.last().get();
1436 generator
.emitNode(leftMostAddChildTempRegister
, leftMostAddChild
);
1438 // Note on ordering of conversions:
1440 // We maintain the same ordering of conversions as we would see if the concatenations
1441 // was performed as a sequence of adds (otherwise this optimization could change
1442 // behaviour should an object have been provided a valueOf or toString method).
1444 // Considering the above example, the sequnce of execution is:
1445 // * evaluate operand (a)
1446 // * evaluate operand (b)
1447 // * convert (a) to primitive <- (this would be triggered by the first add)
1448 // * convert (b) to primitive <- (ditto)
1449 // * evaluate operand (c)
1450 // * convert (c) to primitive <- (this would be triggered by the second add)
1451 // And optionally, if there is an assignment:
1452 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1454 // As such we do not plant an op to convert the leftmost child now. Instead, use
1455 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1456 // once the second node has been generated. However, if the leftmost child is an
1457 // immediate we can trivially determine that no conversion will be required.
1458 // If this is the case
1459 if (leftMostAddChild
->isString())
1460 leftMostAddChildTempRegister
= 0;
1462 while (reverseExpressionList
.size()) {
1463 ExpressionNode
* node
= reverseExpressionList
.last();
1464 reverseExpressionList
.removeLast();
1466 // Emit the code for the current node.
1467 temporaryRegisters
.append(generator
.newTemporary());
1468 generator
.emitNode(temporaryRegisters
.last().get(), node
);
1470 // On the first iteration of this loop, when we first reach this point we have just
1471 // generated the second node, which means it is time to convert the leftmost operand.
1472 if (leftMostAddChildTempRegister
) {
1473 generator
.emitToPrimitive(leftMostAddChildTempRegister
, leftMostAddChildTempRegister
);
1474 leftMostAddChildTempRegister
= 0; // Only do this once.
1476 // Plant a conversion for this node, if necessary.
1477 if (!node
->isString())
1478 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
1480 ASSERT(temporaryRegisters
.size() >= 3);
1482 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1483 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1484 if (emitExpressionInfoForMe
)
1485 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->divotStart(), emitExpressionInfoForMe
->divotEnd());
1486 // If there is an assignment convert the lhs now. This will also copy lhs to
1487 // the temporary register we allocated for it.
1489 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
1491 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
1494 void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1496 TriState branchCondition
;
1497 ExpressionNode
* branchExpression
;
1498 tryFoldToBranch(generator
, branchCondition
, branchExpression
);
1500 if (branchCondition
== MixedTriState
)
1501 ExpressionNode::emitBytecodeInConditionContext(generator
, trueTarget
, falseTarget
, fallThroughMode
);
1502 else if (branchCondition
== TrueTriState
)
1503 generator
.emitNodeInConditionContext(branchExpression
, trueTarget
, falseTarget
, fallThroughMode
);
1505 generator
.emitNodeInConditionContext(branchExpression
, falseTarget
, trueTarget
, invert(fallThroughMode
));
1508 static inline bool canFoldToBranch(OpcodeID opcodeID
, ExpressionNode
* branchExpression
, JSValue constant
)
1510 ResultType expressionType
= branchExpression
->resultDescriptor();
1512 if (expressionType
.definitelyIsBoolean() && constant
.isBoolean())
1514 else if (expressionType
.definitelyIsBoolean() && constant
.isInt32() && (constant
.asInt32() == 0 || constant
.asInt32() == 1))
1515 return opcodeID
== op_eq
|| opcodeID
== op_neq
; // Strict equality is false in the case of type mismatch.
1516 else if (expressionType
.isInt32() && constant
.isInt32() && constant
.asInt32() == 0)
1522 void BinaryOpNode::tryFoldToBranch(BytecodeGenerator
& generator
, TriState
& branchCondition
, ExpressionNode
*& branchExpression
)
1524 branchCondition
= MixedTriState
;
1525 branchExpression
= 0;
1527 ConstantNode
* constant
= 0;
1528 if (m_expr1
->isConstant()) {
1529 constant
= static_cast<ConstantNode
*>(m_expr1
);
1530 branchExpression
= m_expr2
;
1531 } else if (m_expr2
->isConstant()) {
1532 constant
= static_cast<ConstantNode
*>(m_expr2
);
1533 branchExpression
= m_expr1
;
1538 ASSERT(branchExpression
);
1540 OpcodeID opcodeID
= this->opcodeID();
1541 JSValue value
= constant
->jsValue(generator
);
1542 bool canFoldToBranch
= JSC::canFoldToBranch(opcodeID
, branchExpression
, value
);
1543 if (!canFoldToBranch
)
1546 if (opcodeID
== op_eq
|| opcodeID
== op_stricteq
)
1547 branchCondition
= triState(value
.pureToBoolean());
1548 else if (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
)
1549 branchCondition
= triState(!value
.pureToBoolean());
1552 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1554 OpcodeID opcodeID
= this->opcodeID();
1556 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString()) {
1557 generator
.emitExpressionInfo(position(), position(), position());
1558 return emitStrcat(generator
, dst
);
1561 if (opcodeID
== op_neq
) {
1562 if (m_expr1
->isNull() || m_expr2
->isNull()) {
1563 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
1564 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
1565 return generator
.emitUnaryOp(op_neq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
1569 ExpressionNode
* left
= m_expr1
;
1570 ExpressionNode
* right
= m_expr2
;
1571 if (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
) {
1572 if (left
->isString())
1573 std::swap(left
, right
);
1576 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, right
->isPure(generator
));
1577 bool wasTypeof
= generator
.lastOpcodeID() == op_typeof
;
1578 RefPtr
<RegisterID
> src2
= generator
.emitNode(right
);
1579 generator
.emitExpressionInfo(position(), position(), position());
1580 if (wasTypeof
&& (opcodeID
== op_neq
|| opcodeID
== op_nstricteq
)) {
1581 RefPtr
<RegisterID
> tmp
= generator
.tempDestination(dst
);
1582 if (opcodeID
== op_neq
)
1583 generator
.emitEqualityOp(op_eq
, generator
.finalDestination(tmp
.get(), src1
.get()), src1
.get(), src2
.get());
1584 else if (opcodeID
== op_nstricteq
)
1585 generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(tmp
.get(), src1
.get()), src1
.get(), src2
.get());
1587 RELEASE_ASSERT_NOT_REACHED();
1588 return generator
.emitUnaryOp(op_not
, generator
.finalDestination(dst
, tmp
.get()), tmp
.get());
1590 RegisterID
* result
= generator
.emitBinaryOp(opcodeID
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), OperandTypes(left
->resultDescriptor(), right
->resultDescriptor()));
1591 if (opcodeID
== op_urshift
&& dst
!= generator
.ignoredResult())
1592 return generator
.emitUnaryOp(op_unsigned
, result
, result
);
1596 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1598 if (m_expr1
->isNull() || m_expr2
->isNull()) {
1599 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
1600 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
1601 return generator
.emitUnaryOp(op_eq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
1604 ExpressionNode
* left
= m_expr1
;
1605 ExpressionNode
* right
= m_expr2
;
1606 if (left
->isString())
1607 std::swap(left
, right
);
1609 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1610 RefPtr
<RegisterID
> src2
= generator
.emitNode(right
);
1611 return generator
.emitEqualityOp(op_eq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get());
1614 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1616 ExpressionNode
* left
= m_expr1
;
1617 ExpressionNode
* right
= m_expr2
;
1618 if (left
->isString())
1619 std::swap(left
, right
);
1621 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(left
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1622 RefPtr
<RegisterID
> src2
= generator
.emitNode(right
);
1623 return generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get());
1626 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1628 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1629 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
1630 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1631 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
1634 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1636 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1637 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
1638 RefPtr
<RegisterID
> prototype
= generator
.newTemporary();
1639 RefPtr
<RegisterID
> dstReg
= generator
.finalDestination(dst
, src1
.get());
1640 RefPtr
<Label
> target
= generator
.newLabel();
1642 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1643 generator
.emitCheckHasInstance(dstReg
.get(), src1
.get(), src2
.get(), target
.get());
1645 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1646 generator
.emitGetById(prototype
.get(), src2
.get(), generator
.vm()->propertyNames
->prototype
);
1648 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1649 RegisterID
* result
= generator
.emitInstanceOf(dstReg
.get(), src1
.get(), prototype
.get());
1650 generator
.emitLabel(target
.get());
1654 // ------------------------------ LogicalOpNode ----------------------------
1656 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1658 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
1659 RefPtr
<Label
> target
= generator
.newLabel();
1661 generator
.emitNode(temp
.get(), m_expr1
);
1662 if (m_operator
== OpLogicalAnd
)
1663 generator
.emitJumpIfFalse(temp
.get(), target
.get());
1665 generator
.emitJumpIfTrue(temp
.get(), target
.get());
1666 generator
.emitNode(temp
.get(), m_expr2
);
1667 generator
.emitLabel(target
.get());
1669 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
1672 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, FallThroughMode fallThroughMode
)
1674 RefPtr
<Label
> afterExpr1
= generator
.newLabel();
1675 if (m_operator
== OpLogicalAnd
)
1676 generator
.emitNodeInConditionContext(m_expr1
, afterExpr1
.get(), falseTarget
, FallThroughMeansTrue
);
1678 generator
.emitNodeInConditionContext(m_expr1
, trueTarget
, afterExpr1
.get(), FallThroughMeansFalse
);
1679 generator
.emitLabel(afterExpr1
.get());
1681 generator
.emitNodeInConditionContext(m_expr2
, trueTarget
, falseTarget
, fallThroughMode
);
1684 // ------------------------------ ConditionalNode ------------------------------
1686 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1688 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
1689 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1690 RefPtr
<Label
> afterElse
= generator
.newLabel();
1692 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1693 generator
.emitNodeInConditionContext(m_logical
, beforeThen
.get(), beforeElse
.get(), FallThroughMeansTrue
);
1694 generator
.emitLabel(beforeThen
.get());
1696 generator
.emitProfileControlFlow(m_expr1
->startOffset());
1697 generator
.emitNode(newDst
.get(), m_expr1
);
1698 generator
.emitJump(afterElse
.get());
1700 generator
.emitLabel(beforeElse
.get());
1701 generator
.emitProfileControlFlow(m_expr1
->endOffset() + 1);
1702 generator
.emitNode(newDst
.get(), m_expr2
);
1704 generator
.emitLabel(afterElse
.get());
1706 generator
.emitProfileControlFlow(m_expr2
->endOffset() + 1);
1708 return newDst
.get();
1711 // ------------------------------ ReadModifyResolveNode -----------------------------------
1713 // FIXME: should this be moved to be a method on BytecodeGenerator?
1714 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1725 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1726 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1733 opcodeID
= op_lshift
;
1736 opcodeID
= op_rshift
;
1739 opcodeID
= op_urshift
;
1742 opcodeID
= op_bitand
;
1745 opcodeID
= op_bitxor
;
1748 opcodeID
= op_bitor
;
1754 RELEASE_ASSERT_NOT_REACHED();
1758 RegisterID
* src2
= generator
.emitNode(m_right
);
1760 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1761 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1762 if (emitExpressionInfoForMe
)
1763 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->divotStart(), emitExpressionInfoForMe
->divotEnd());
1764 RegisterID
* result
= generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1765 if (oper
== OpURShift
)
1766 return generator
.emitUnaryOp(op_unsigned
, result
, result
);
1770 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1772 JSTextPosition newDivot
= divotStart() + m_ident
.length();
1773 Variable var
= generator
.variable(m_ident
);
1774 if (RegisterID
* local
= var
.local()) {
1775 if (var
.isReadOnly()) {
1776 generator
.emitReadOnlyExceptionIfNeeded();
1777 return emitReadModifyAssignment(generator
, generator
.finalDestination(dst
), local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1780 if (generator
.vm()->typeProfiler()
1781 || generator
.leftHandSideNeedsCopy(m_rightHasAssignments
, m_right
->isPure(generator
))) {
1782 RefPtr
<RegisterID
> result
= generator
.newTemporary();
1783 generator
.emitMove(result
.get(), local
);
1784 emitReadModifyAssignment(generator
, result
.get(), result
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1785 generator
.emitMove(local
, result
.get());
1786 generator
.invalidateForInContextForLocal(local
);
1787 if (generator
.vm()->typeProfiler())
1788 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1789 return generator
.moveToDestinationIfNeeded(dst
, result
.get());
1792 RegisterID
* result
= emitReadModifyAssignment(generator
, local
, local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1793 generator
.invalidateForInContextForLocal(local
);
1794 return generator
.moveToDestinationIfNeeded(dst
, result
);
1797 generator
.emitExpressionInfo(newDivot
, divotStart(), newDivot
);
1798 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(nullptr, var
);
1799 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), var
, ThrowIfNotFound
);
1800 RefPtr
<RegisterID
> result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()), this);
1801 RegisterID
* returnResult
= generator
.emitPutToScope(scope
.get(), var
, result
.get(), ThrowIfNotFound
);
1802 if (generator
.vm()->typeProfiler()) {
1803 generator
.emitProfileType(result
.get(), var
.isResolved() ? ProfileTypeBytecodePutToLocalScope
: ProfileTypeBytecodePutToScope
, &m_ident
);
1804 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1806 return returnResult
;
1809 // ------------------------------ AssignResolveNode -----------------------------------
1811 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1813 Variable var
= generator
.variable(m_ident
);
1814 if (RegisterID
* local
= var
.local()) {
1815 if (var
.isReadOnly()) {
1816 generator
.emitReadOnlyExceptionIfNeeded();
1817 return generator
.emitNode(dst
, m_right
);
1819 if (var
.isSpecial() || generator
.vm()->typeProfiler()) {
1820 RefPtr
<RegisterID
> tempDst
= generator
.tempDestination(dst
);
1821 generator
.emitNode(tempDst
.get(), m_right
);
1822 generator
.emitMove(local
, tempDst
.get());
1823 generator
.invalidateForInContextForLocal(local
);
1824 if (generator
.vm()->typeProfiler())
1825 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1826 return generator
.moveToDestinationIfNeeded(dst
, tempDst
.get());
1828 RegisterID
* result
= generator
.emitNode(local
, m_right
);
1829 generator
.invalidateForInContextForLocal(local
);
1830 return generator
.moveToDestinationIfNeeded(dst
, result
);
1833 if (generator
.isStrictMode())
1834 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1835 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(nullptr, var
);
1836 if (dst
== generator
.ignoredResult())
1838 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_right
);
1839 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1840 RegisterID
* returnResult
= generator
.emitPutToScope(scope
.get(), var
, result
.get(), generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
1841 if (generator
.vm()->typeProfiler()) {
1842 generator
.emitProfileType(result
.get(), var
.isResolved() ? ProfileTypeBytecodePutToLocalScope
: ProfileTypeBytecodePutToScope
, &m_ident
);
1843 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1845 return returnResult
;
1848 // ------------------------------ AssignDotNode -----------------------------------
1850 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1852 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1853 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1854 RefPtr
<RegisterID
> result
= generator
.emitNode(value
.get(), m_right
);
1855 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1856 RegisterID
* forwardResult
= (dst
== generator
.ignoredResult()) ? result
.get() : generator
.moveToDestinationIfNeeded(generator
.tempDestination(result
.get()), result
.get());
1857 generator
.emitPutById(base
.get(), m_ident
, forwardResult
);
1858 if (generator
.vm()->typeProfiler()) {
1859 generator
.emitProfileType(forwardResult
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1860 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1862 return generator
.moveToDestinationIfNeeded(dst
, forwardResult
);
1865 // ------------------------------ ReadModifyDotNode -----------------------------------
1867 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1869 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1871 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1872 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
1873 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()));
1875 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1876 RegisterID
* ret
= generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1877 if (generator
.vm()->typeProfiler()) {
1878 generator
.emitProfileType(updatedValue
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1879 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1884 // ------------------------------ AssignErrorNode -----------------------------------
1886 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1888 return emitThrowReferenceError(generator
, ASCIILiteral("Left side of assignment is not a reference."));
1891 // ------------------------------ AssignBracketNode -----------------------------------
1893 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1895 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1896 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1897 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1898 RefPtr
<RegisterID
> result
= generator
.emitNode(value
.get(), m_right
);
1900 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1901 RegisterID
* forwardResult
= (dst
== generator
.ignoredResult()) ? result
.get() : generator
.moveToDestinationIfNeeded(generator
.tempDestination(result
.get()), result
.get());
1903 if (m_subscript
->isString())
1904 generator
.emitPutById(base
.get(), static_cast<StringNode
*>(m_subscript
)->value(), forwardResult
);
1906 generator
.emitPutByVal(base
.get(), property
.get(), forwardResult
);
1908 if (generator
.vm()->typeProfiler()) {
1909 generator
.emitProfileType(forwardResult
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1910 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1912 return generator
.moveToDestinationIfNeeded(dst
, forwardResult
);
1915 // ------------------------------ ReadModifyBracketNode -----------------------------------
1917 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1919 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1920 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1922 generator
.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1923 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
1924 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()));
1926 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
1927 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1928 if (generator
.vm()->typeProfiler()) {
1929 generator
.emitProfileType(updatedValue
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
1930 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
1933 return updatedValue
;
1936 // ------------------------------ CommaNode ------------------------------------
1938 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1940 CommaNode
* node
= this;
1941 for (; node
&& node
->next(); node
= node
->next())
1942 generator
.emitNode(generator
.ignoredResult(), node
->m_expr
);
1943 return generator
.emitNode(dst
, node
->m_expr
);
1946 // ------------------------------ ConstDeclNode ------------------------------------
1948 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1950 // FIXME: This code does not match the behavior of const in Firefox.
1951 Variable var
= generator
.variable(m_ident
);
1952 if (RegisterID
* local
= var
.local()) {
1956 // FIXME: Maybe call emitExpressionInfo here.
1957 if (var
.isSpecial() || generator
.vm()->typeProfiler()) {
1958 RefPtr
<RegisterID
> tempDst
= generator
.newTemporary();
1959 generator
.emitNode(tempDst
.get(), m_init
);
1960 return generator
.emitMove(local
, tempDst
.get());
1963 return generator
.emitNode(local
, m_init
);
1966 RefPtr
<RegisterID
> value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1968 if (generator
.codeType() == GlobalCode
)
1969 return generator
.emitInitGlobalConst(m_ident
, value
.get());
1971 if (generator
.codeType() != EvalCode
) {
1972 // Do a special kind of resolution. If anything fails, then don't perform the assignment. This is
1973 // pretty shady - particularly how negligent it is with inteleaving scopes - but it's the
1974 // behavior that JSC has had for a long time.
1976 ASSERT(generator
.codeType() == FunctionCode
);
1978 var
= generator
.variablePerSymbolTable(m_ident
);
1979 if (!var
.isResolved())
1982 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(generator
.newTemporary(), var
);
1983 return generator
.emitPutToScope(scope
.get(), var
, value
.get(), DoNotThrowIfNotFound
);
1986 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
1987 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(nullptr, var
);
1988 return generator
.emitPutToScope(scope
.get(), var
, value
.get(), DoNotThrowIfNotFound
);
1991 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1993 RegisterID
* result
= 0;
1994 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1995 result
= n
->emitCodeSingle(generator
);
2000 // ------------------------------ ConstStatementNode -----------------------------
2002 void ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2004 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2005 generator
.emitNode(m_next
);
2008 // ------------------------------ SourceElements -------------------------------
2011 inline StatementNode
* SourceElements::lastStatement() const
2016 inline void SourceElements::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2018 for (StatementNode
* statement
= m_head
; statement
; statement
= statement
->next())
2019 generator
.emitNode(dst
, statement
);
2022 // ------------------------------ BlockNode ------------------------------------
2024 inline StatementNode
* BlockNode::lastStatement() const
2026 return m_statements
? m_statements
->lastStatement() : 0;
2029 StatementNode
* BlockNode::singleStatement() const
2031 return m_statements
? m_statements
->singleStatement() : 0;
2034 void BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2038 m_statements
->emitBytecode(generator
, dst
);
2041 // ------------------------------ EmptyStatementNode ---------------------------
2043 void EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2045 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2048 // ------------------------------ DebuggerStatementNode ---------------------------
2050 void DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2052 generator
.emitDebugHook(DidReachBreakpoint
, lastLine(), startOffset(), lineStartOffset());
2055 // ------------------------------ ExprStatementNode ----------------------------
2057 void ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2060 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2061 generator
.emitNode(dst
, m_expr
);
2064 // ------------------------------ VarStatementNode ----------------------------
2066 void VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2069 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2070 generator
.emitNode(m_expr
);
2073 // ------------------------------ EmptyVarExpression ----------------------------
2075 RegisterID
* EmptyVarExpression::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2077 if (!generator
.vm()->typeProfiler())
2080 Variable var
= generator
.variable(m_ident
);
2081 if (RegisterID
* local
= var
.local())
2082 generator
.emitProfileType(local
, ProfileTypeBytecodeHasGlobalID
, nullptr);
2084 RefPtr
<RegisterID
> scope
= generator
.emitResolveScope(nullptr, var
);
2085 RefPtr
<RegisterID
> value
= generator
.emitGetFromScope(generator
.newTemporary(), scope
.get(), var
, DoNotThrowIfNotFound
);
2086 generator
.emitProfileType(value
.get(), var
.isResolved() ? ProfileTypeBytecodeGetFromLocalScope
: ProfileTypeBytecodeGetFromScope
, &m_ident
);
2089 generator
.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset
+ m_ident
.length(), -1));
2091 // It's safe to return null here because this node will always be a child node of VarStatementNode which ignores our return value.
2095 // ------------------------------ IfElseNode ---------------------------------------
2097 static inline StatementNode
* singleStatement(StatementNode
* statementNode
)
2099 if (statementNode
->isBlock())
2100 return static_cast<BlockNode
*>(statementNode
)->singleStatement();
2101 return statementNode
;
2104 bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator
& generator
, StatementNode
* ifBlock
,
2105 Label
*& trueTarget
, FallThroughMode
& fallThroughMode
)
2107 StatementNode
* singleStatement
= JSC::singleStatement(ifBlock
);
2108 if (!singleStatement
)
2111 if (singleStatement
->isBreak()) {
2112 BreakNode
* breakNode
= static_cast<BreakNode
*>(singleStatement
);
2113 Label
* target
= breakNode
->trivialTarget(generator
);
2116 trueTarget
= target
;
2117 fallThroughMode
= FallThroughMeansFalse
;
2121 if (singleStatement
->isContinue()) {
2122 ContinueNode
* continueNode
= static_cast<ContinueNode
*>(singleStatement
);
2123 Label
* target
= continueNode
->trivialTarget(generator
);
2126 trueTarget
= target
;
2127 fallThroughMode
= FallThroughMeansFalse
;
2134 void IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2136 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2138 RefPtr
<Label
> beforeThen
= generator
.newLabel();
2139 RefPtr
<Label
> beforeElse
= generator
.newLabel();
2140 RefPtr
<Label
> afterElse
= generator
.newLabel();
2142 Label
* trueTarget
= beforeThen
.get();
2143 Label
* falseTarget
= beforeElse
.get();
2144 FallThroughMode fallThroughMode
= FallThroughMeansTrue
;
2145 bool didFoldIfBlock
= tryFoldBreakAndContinue(generator
, m_ifBlock
, trueTarget
, fallThroughMode
);
2147 generator
.emitNodeInConditionContext(m_condition
, trueTarget
, falseTarget
, fallThroughMode
);
2148 generator
.emitLabel(beforeThen
.get());
2149 generator
.emitProfileControlFlow(m_ifBlock
->startOffset());
2151 if (!didFoldIfBlock
) {
2152 generator
.emitNode(dst
, m_ifBlock
);
2154 generator
.emitJump(afterElse
.get());
2157 generator
.emitLabel(beforeElse
.get());
2160 generator
.emitProfileControlFlow(m_ifBlock
->endOffset() + (m_ifBlock
->isBlock() ? 1 : 0));
2161 generator
.emitNode(dst
, m_elseBlock
);
2164 generator
.emitLabel(afterElse
.get());
2165 StatementNode
* endingBlock
= m_elseBlock
? m_elseBlock
: m_ifBlock
;
2166 generator
.emitProfileControlFlow(endingBlock
->endOffset() + (endingBlock
->isBlock() ? 1 : 0));
2169 // ------------------------------ DoWhileNode ----------------------------------
2171 void DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2173 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
2175 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
2176 generator
.emitLabel(topOfLoop
.get());
2177 generator
.emitLoopHint();
2178 generator
.emitDebugHook(WillExecuteStatement
, lastLine(), startOffset(), lineStartOffset());
2180 generator
.emitNode(dst
, m_statement
);
2182 generator
.emitLabel(scope
->continueTarget());
2183 generator
.emitDebugHook(WillExecuteStatement
, lastLine(), startOffset(), lineStartOffset());
2184 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
2186 generator
.emitLabel(scope
->breakTarget());
2189 // ------------------------------ WhileNode ------------------------------------
2191 void WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2193 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
2194 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
2196 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->firstLine(), m_expr
->startOffset(), m_expr
->lineStartOffset());
2197 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansTrue
);
2199 generator
.emitLabel(topOfLoop
.get());
2200 generator
.emitLoopHint();
2202 generator
.emitProfileControlFlow(m_statement
->startOffset());
2203 generator
.emitNode(dst
, m_statement
);
2205 generator
.emitLabel(scope
->continueTarget());
2206 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2208 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
2210 generator
.emitLabel(scope
->breakTarget());
2212 generator
.emitProfileControlFlow(m_statement
->endOffset() + (m_statement
->isBlock() ? 1 : 0));
2215 // ------------------------------ ForNode --------------------------------------
2217 void ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2219 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
2221 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2224 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
2226 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
2228 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansTrue
);
2230 generator
.emitLabel(topOfLoop
.get());
2231 generator
.emitLoopHint();
2232 generator
.emitProfileControlFlow(m_statement
->startOffset());
2234 generator
.emitNode(dst
, m_statement
);
2236 generator
.emitLabel(scope
->continueTarget());
2237 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2239 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
2242 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), FallThroughMeansFalse
);
2244 generator
.emitJump(topOfLoop
.get());
2246 generator
.emitLabel(scope
->breakTarget());
2247 generator
.emitProfileControlFlow(m_statement
->endOffset() + (m_statement
->isBlock() ? 1 : 0));
2250 // ------------------------------ ForInNode ------------------------------------
2252 RegisterID
* ForInNode::tryGetBoundLocal(BytecodeGenerator
& generator
)
2254 if (m_lexpr
->isResolveNode()) {
2255 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
2256 return generator
.variable(ident
).local();
2259 if (m_lexpr
->isDestructuringNode()) {
2260 DestructuringAssignmentNode
* assignNode
= static_cast<DestructuringAssignmentNode
*>(m_lexpr
);
2261 auto binding
= assignNode
->bindings();
2262 if (!binding
->isBindingNode())
2265 auto simpleBinding
= static_cast<BindingNode
*>(binding
);
2266 const Identifier
& ident
= simpleBinding
->boundProperty();
2267 Variable var
= generator
.variable(ident
);
2268 if (var
.isSpecial())
2276 void ForInNode::emitLoopHeader(BytecodeGenerator
& generator
, RegisterID
* propertyName
)
2278 if (m_lexpr
->isResolveNode()) {
2279 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
2280 Variable var
= generator
.variable(ident
);
2281 if (RegisterID
* local
= var
.local())
2282 generator
.emitMove(local
, propertyName
);
2284 if (generator
.isStrictMode())
2285 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
2286 RegisterID
* scope
= generator
.emitResolveScope(nullptr, var
);
2287 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
2288 generator
.emitPutToScope(scope
, var
, propertyName
, generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
2289 if (generator
.vm()->typeProfiler())
2290 generator
.emitProfileType(propertyName
, var
.isResolved() ? ProfileTypeBytecodePutToLocalScope
: ProfileTypeBytecodePutToScope
, &ident
);
2292 if (generator
.vm()->typeProfiler())
2293 generator
.emitTypeProfilerExpressionInfo(m_lexpr
->position(), JSTextPosition(-1, m_lexpr
->position().offset
+ ident
.length(), -1));
2296 if (m_lexpr
->isDotAccessorNode()) {
2297 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
2298 const Identifier
& ident
= assignNode
->identifier();
2299 RegisterID
* base
= generator
.emitNode(assignNode
->base());
2300 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
2301 generator
.emitPutById(base
, ident
, propertyName
);
2302 if (generator
.vm()->typeProfiler()) {
2303 generator
.emitProfileType(propertyName
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
2304 generator
.emitTypeProfilerExpressionInfo(assignNode
->divotStart(), assignNode
->divotEnd());
2308 if (m_lexpr
->isBracketAccessorNode()) {
2309 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
2310 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
2311 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
2312 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
2313 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
2314 if (generator
.vm()->typeProfiler()) {
2315 generator
.emitProfileType(propertyName
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
2316 generator
.emitTypeProfilerExpressionInfo(assignNode
->divotStart(), assignNode
->divotEnd());
2321 if (m_lexpr
->isDestructuringNode()) {
2322 DestructuringAssignmentNode
* assignNode
= static_cast<DestructuringAssignmentNode
*>(m_lexpr
);
2323 auto binding
= assignNode
->bindings();
2324 if (!binding
->isBindingNode()) {
2325 assignNode
->bindings()->bindValue(generator
, propertyName
);
2329 auto simpleBinding
= static_cast<BindingNode
*>(binding
);
2330 const Identifier
& ident
= simpleBinding
->boundProperty();
2331 Variable var
= generator
.variable(ident
);
2332 if (!var
.local() || var
.isSpecial()) {
2333 assignNode
->bindings()->bindValue(generator
, propertyName
);
2336 generator
.emitMove(var
.local(), propertyName
);
2337 if (generator
.vm()->typeProfiler())
2338 generator
.emitTypeProfilerExpressionInfo(simpleBinding
->divotStart(), simpleBinding
->divotEnd());
2342 RELEASE_ASSERT_NOT_REACHED();
2345 void ForInNode::emitMultiLoopBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2347 if (!m_lexpr
->isAssignmentLocation()) {
2348 emitThrowReferenceError(generator
, ASCIILiteral("Left side of for-in statement is not a reference."));
2352 RefPtr
<Label
> end
= generator
.newLabel();
2354 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2356 RefPtr
<RegisterID
> base
= generator
.newTemporary();
2357 RefPtr
<RegisterID
> length
;
2358 RefPtr
<RegisterID
> enumerator
;
2359 generator
.emitNode(base
.get(), m_expr
);
2360 RefPtr
<RegisterID
> local
= this->tryGetBoundLocal(generator
);
2361 RefPtr
<RegisterID
> enumeratorIndex
;
2363 int profilerStartOffset
= m_statement
->startOffset();
2364 int profilerEndOffset
= m_statement
->endOffset() + (m_statement
->isBlock() ? 1 : 0);
2366 enumerator
= generator
.emitGetPropertyEnumerator(generator
.newTemporary(), base
.get());
2368 // Indexed property loop.
2370 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
2371 RefPtr
<Label
> loopStart
= generator
.newLabel();
2372 RefPtr
<Label
> loopEnd
= generator
.newLabel();
2374 length
= generator
.emitGetEnumerableLength(generator
.newTemporary(), enumerator
.get());
2375 RefPtr
<RegisterID
> i
= generator
.emitLoad(generator
.newTemporary(), jsNumber(0));
2376 RefPtr
<RegisterID
> propertyName
= generator
.newTemporary();
2378 generator
.emitLabel(loopStart
.get());
2379 generator
.emitLoopHint();
2381 RefPtr
<RegisterID
> result
= generator
.emitEqualityOp(op_less
, generator
.newTemporary(), i
.get(), length
.get());
2382 generator
.emitJumpIfFalse(result
.get(), loopEnd
.get());
2383 generator
.emitHasIndexedProperty(result
.get(), base
.get(), i
.get());
2384 generator
.emitJumpIfFalse(result
.get(), scope
->continueTarget());
2386 generator
.emitToIndexString(propertyName
.get(), i
.get());
2387 this->emitLoopHeader(generator
, propertyName
.get());
2389 generator
.emitProfileControlFlow(profilerStartOffset
);
2391 generator
.pushIndexedForInScope(local
.get(), i
.get());
2392 generator
.emitNode(dst
, m_statement
);
2393 generator
.popIndexedForInScope(local
.get());
2395 generator
.emitProfileControlFlow(profilerEndOffset
);
2397 generator
.emitLabel(scope
->continueTarget());
2398 generator
.emitInc(i
.get());
2399 generator
.emitJump(loopStart
.get());
2401 generator
.emitLabel(scope
->breakTarget());
2402 generator
.emitJump(end
.get());
2403 generator
.emitLabel(loopEnd
.get());
2406 // Structure property loop.
2408 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
2409 RefPtr
<Label
> loopStart
= generator
.newLabel();
2410 RefPtr
<Label
> loopEnd
= generator
.newLabel();
2412 enumeratorIndex
= generator
.emitLoad(generator
.newTemporary(), jsNumber(0));
2413 RefPtr
<RegisterID
> propertyName
= generator
.newTemporary();
2414 generator
.emitEnumeratorStructurePropertyName(propertyName
.get(), enumerator
.get(), enumeratorIndex
.get());
2416 generator
.emitLabel(loopStart
.get());
2417 generator
.emitLoopHint();
2419 RefPtr
<RegisterID
> result
= generator
.emitUnaryOp(op_eq_null
, generator
.newTemporary(), propertyName
.get());
2420 generator
.emitJumpIfTrue(result
.get(), loopEnd
.get());
2421 generator
.emitHasStructureProperty(result
.get(), base
.get(), propertyName
.get(), enumerator
.get());
2422 generator
.emitJumpIfFalse(result
.get(), scope
->continueTarget());
2424 this->emitLoopHeader(generator
, propertyName
.get());
2426 generator
.emitProfileControlFlow(profilerStartOffset
);
2428 generator
.pushStructureForInScope(local
.get(), enumeratorIndex
.get(), propertyName
.get(), enumerator
.get());
2429 generator
.emitNode(dst
, m_statement
);
2430 generator
.popStructureForInScope(local
.get());
2432 generator
.emitProfileControlFlow(profilerEndOffset
);
2434 generator
.emitLabel(scope
->continueTarget());
2435 generator
.emitInc(enumeratorIndex
.get());
2436 generator
.emitEnumeratorStructurePropertyName(propertyName
.get(), enumerator
.get(), enumeratorIndex
.get());
2437 generator
.emitJump(loopStart
.get());
2439 generator
.emitLabel(scope
->breakTarget());
2440 generator
.emitJump(end
.get());
2441 generator
.emitLabel(loopEnd
.get());
2444 // Generic property loop.
2446 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Loop
);
2447 RefPtr
<Label
> loopStart
= generator
.newLabel();
2448 RefPtr
<Label
> loopEnd
= generator
.newLabel();
2450 RefPtr
<RegisterID
> propertyName
= generator
.newTemporary();
2452 generator
.emitEnumeratorGenericPropertyName(propertyName
.get(), enumerator
.get(), enumeratorIndex
.get());
2454 generator
.emitLabel(loopStart
.get());
2455 generator
.emitLoopHint();
2457 RefPtr
<RegisterID
> result
= generator
.emitUnaryOp(op_eq_null
, generator
.newTemporary(), propertyName
.get());
2458 generator
.emitJumpIfTrue(result
.get(), loopEnd
.get());
2460 generator
.emitHasGenericProperty(result
.get(), base
.get(), propertyName
.get());
2461 generator
.emitJumpIfFalse(result
.get(), scope
->continueTarget());
2463 this->emitLoopHeader(generator
, propertyName
.get());
2465 generator
.emitProfileControlFlow(profilerStartOffset
);
2467 generator
.emitNode(dst
, m_statement
);
2469 generator
.emitLabel(scope
->continueTarget());
2470 generator
.emitInc(enumeratorIndex
.get());
2471 generator
.emitEnumeratorGenericPropertyName(propertyName
.get(), enumerator
.get(), enumeratorIndex
.get());
2472 generator
.emitJump(loopStart
.get());
2474 generator
.emitLabel(scope
->breakTarget());
2475 generator
.emitJump(end
.get());
2476 generator
.emitLabel(loopEnd
.get());
2479 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2480 generator
.emitLabel(end
.get());
2481 generator
.emitProfileControlFlow(profilerEndOffset
);
2484 void ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2486 this->emitMultiLoopBytecode(generator
, dst
);
2489 // ------------------------------ ForOfNode ------------------------------------
2490 void ForOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2492 if (!m_lexpr
->isAssignmentLocation()) {
2493 emitThrowReferenceError(generator
, ASCIILiteral("Left side of for-of statement is not a reference."));
2497 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2498 auto extractor
= [this, dst
](BytecodeGenerator
& generator
, RegisterID
* value
)
2500 if (m_lexpr
->isResolveNode()) {
2501 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
2502 Variable var
= generator
.variable(ident
);
2503 if (RegisterID
* local
= var
.local())
2504 generator
.emitMove(local
, value
);
2506 if (generator
.isStrictMode())
2507 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
2508 RegisterID
* scope
= generator
.emitResolveScope(nullptr, var
);
2509 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
2510 generator
.emitPutToScope(scope
, var
, value
, generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
2511 if (generator
.vm()->typeProfiler())
2512 generator
.emitProfileType(value
, var
.isResolved() ? ProfileTypeBytecodePutToLocalScope
: ProfileTypeBytecodePutToScope
, &ident
);
2514 if (generator
.vm()->typeProfiler())
2515 generator
.emitTypeProfilerExpressionInfo(m_lexpr
->position(), JSTextPosition(-1, m_lexpr
->position().offset
+ ident
.length(), -1));
2516 } else if (m_lexpr
->isDotAccessorNode()) {
2517 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
2518 const Identifier
& ident
= assignNode
->identifier();
2519 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
2521 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
2522 generator
.emitPutById(base
.get(), ident
, value
);
2523 if (generator
.vm()->typeProfiler()) {
2524 generator
.emitProfileType(value
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
2525 generator
.emitTypeProfilerExpressionInfo(assignNode
->divotStart(), assignNode
->divotEnd());
2527 } else if (m_lexpr
->isBracketAccessorNode()) {
2528 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
2529 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
2530 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
2532 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->divotStart(), assignNode
->divotEnd());
2533 generator
.emitPutByVal(base
.get(), subscript
, value
);
2534 if (generator
.vm()->typeProfiler()) {
2535 generator
.emitProfileType(value
, ProfileTypeBytecodeDoesNotHaveGlobalID
, nullptr);
2536 generator
.emitTypeProfilerExpressionInfo(assignNode
->divotStart(), assignNode
->divotEnd());
2539 ASSERT(m_lexpr
->isDestructuringNode());
2540 DestructuringAssignmentNode
* assignNode
= static_cast<DestructuringAssignmentNode
*>(m_lexpr
);
2541 assignNode
->bindings()->bindValue(generator
, value
);
2543 generator
.emitProfileControlFlow(m_statement
->startOffset());
2544 generator
.emitNode(dst
, m_statement
);
2546 generator
.emitEnumeration(this, m_expr
, extractor
);
2547 generator
.emitProfileControlFlow(m_statement
->endOffset() + (m_statement
->isBlock() ? 1 : 0));
2550 // ------------------------------ ContinueNode ---------------------------------
2552 Label
* ContinueNode::trivialTarget(BytecodeGenerator
& generator
)
2554 if (generator
.shouldEmitDebugHooks())
2557 LabelScopePtr scope
= generator
.continueTarget(m_ident
);
2560 if (generator
.scopeDepth() != scope
->scopeDepth())
2563 return scope
->continueTarget();
2566 void ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2568 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2570 LabelScopePtr scope
= generator
.continueTarget(m_ident
);
2573 generator
.emitPopScopes(generator
.scopeRegister(), scope
->scopeDepth());
2574 generator
.emitJump(scope
->continueTarget());
2576 generator
.emitProfileControlFlow(endOffset());
2579 // ------------------------------ BreakNode ------------------------------------
2581 Label
* BreakNode::trivialTarget(BytecodeGenerator
& generator
)
2583 if (generator
.shouldEmitDebugHooks())
2586 LabelScopePtr scope
= generator
.breakTarget(m_ident
);
2589 if (generator
.scopeDepth() != scope
->scopeDepth())
2592 return scope
->breakTarget();
2595 void BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2597 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2599 LabelScopePtr scope
= generator
.breakTarget(m_ident
);
2602 generator
.emitPopScopes(generator
.scopeRegister(), scope
->scopeDepth());
2603 generator
.emitJump(scope
->breakTarget());
2605 generator
.emitProfileControlFlow(endOffset());
2608 // ------------------------------ ReturnNode -----------------------------------
2610 void ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2612 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2613 ASSERT(generator
.codeType() == FunctionCode
);
2615 if (dst
== generator
.ignoredResult())
2618 RefPtr
<RegisterID
> returnRegister
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
2619 if (generator
.vm()->typeProfiler()) {
2620 generator
.emitProfileType(returnRegister
.get(), ProfileTypeBytecodeFunctionReturnStatement
, nullptr);
2621 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
2623 if (generator
.scopeDepth()) {
2624 returnRegister
= generator
.emitMove(generator
.newTemporary(), returnRegister
.get());
2625 generator
.emitPopScopes(generator
.scopeRegister(), 0);
2628 generator
.emitDebugHook(WillLeaveCallFrame
, lastLine(), startOffset(), lineStartOffset());
2629 generator
.emitReturn(returnRegister
.get());
2630 generator
.emitProfileControlFlow(endOffset());
2631 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
2632 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
2633 if (generator
.vm()->controlFlowProfiler())
2634 generator
.emitReturn(generator
.emitLoad(nullptr, jsUndefined()));
2637 // ------------------------------ WithNode -------------------------------------
2639 void WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2641 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2643 RefPtr
<RegisterID
> scope
= generator
.emitNode(m_expr
);
2644 generator
.emitExpressionInfo(m_divot
, m_divot
- m_expressionLength
, m_divot
);
2645 generator
.emitPushWithScope(generator
.scopeRegister(), scope
.get());
2646 generator
.emitNode(dst
, m_statement
);
2647 generator
.emitPopScope(generator
.scopeRegister());
2650 // ------------------------------ CaseClauseNode --------------------------------
2652 inline void CaseClauseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2654 generator
.emitProfileControlFlow(m_startOffset
);
2657 m_statements
->emitBytecode(generator
, dst
);
2660 // ------------------------------ CaseBlockNode --------------------------------
2669 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
2671 for (; list
; list
= list
->getNext()) {
2672 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
2673 literalVector
.append(clauseExpression
);
2674 if (clauseExpression
->isNumber()) {
2675 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
2676 int32_t intVal
= static_cast<int32_t>(value
);
2677 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
2678 typeForTable
= SwitchNeither
;
2681 if (intVal
< min_num
)
2683 if (intVal
> max_num
)
2685 typeForTable
= SwitchNumber
;
2688 if (clauseExpression
->isString()) {
2689 if (typeForTable
& ~SwitchString
) {
2690 typeForTable
= SwitchNeither
;
2693 const String
& value
= static_cast<StringNode
*>(clauseExpression
)->value().string();
2694 if (singleCharacterSwitch
&= value
.length() == 1) {
2695 int32_t intVal
= value
[0];
2696 if (intVal
< min_num
)
2698 if (intVal
> max_num
)
2701 typeForTable
= SwitchString
;
2704 typeForTable
= SwitchNeither
;
2709 static inline size_t length(ClauseListNode
* list1
, ClauseListNode
* list2
)
2712 for (ClauseListNode
* node
= list1
; node
; node
= node
->getNext())
2714 for (ClauseListNode
* node
= list2
; node
; node
= node
->getNext())
2719 SwitchInfo::SwitchType
CaseBlockNode::tryTableSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
2721 if (length(m_list1
, m_list2
) < s_tableSwitchMinimum
)
2722 return SwitchInfo::SwitchNone
;
2724 SwitchKind typeForTable
= SwitchUnset
;
2725 bool singleCharacterSwitch
= true;
2727 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
2728 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
2730 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
2731 return SwitchInfo::SwitchNone
;
2733 if (typeForTable
== SwitchNumber
) {
2734 int32_t range
= max_num
- min_num
;
2735 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
2736 return SwitchInfo::SwitchImmediate
;
2737 return SwitchInfo::SwitchNone
;
2740 ASSERT(typeForTable
== SwitchString
);
2742 if (singleCharacterSwitch
) {
2743 int32_t range
= max_num
- min_num
;
2744 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
2745 return SwitchInfo::SwitchCharacter
;
2748 return SwitchInfo::SwitchString
;
2751 void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
2753 RefPtr
<Label
> defaultLabel
;
2754 Vector
<RefPtr
<Label
>, 8> labelVector
;
2755 Vector
<ExpressionNode
*, 8> literalVector
;
2756 int32_t min_num
= std::numeric_limits
<int32_t>::max();
2757 int32_t max_num
= std::numeric_limits
<int32_t>::min();
2758 SwitchInfo::SwitchType switchType
= tryTableSwitch(literalVector
, min_num
, max_num
);
2760 if (switchType
!= SwitchInfo::SwitchNone
) {
2761 // Prepare the various labels
2762 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
2763 labelVector
.append(generator
.newLabel());
2764 defaultLabel
= generator
.newLabel();
2765 generator
.beginSwitch(switchExpression
, switchType
);
2768 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
2769 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
2770 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
2771 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
2772 labelVector
.append(generator
.newLabel());
2773 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
2776 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
2777 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
2778 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
2779 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
2780 labelVector
.append(generator
.newLabel());
2781 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
2783 defaultLabel
= generator
.newLabel();
2784 generator
.emitJump(defaultLabel
.get());
2788 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
2789 generator
.emitLabel(labelVector
[i
++].get());
2790 list
->getClause()->emitBytecode(generator
, dst
);
2793 if (m_defaultClause
) {
2794 generator
.emitLabel(defaultLabel
.get());
2795 m_defaultClause
->emitBytecode(generator
, dst
);
2798 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
2799 generator
.emitLabel(labelVector
[i
++].get());
2800 list
->getClause()->emitBytecode(generator
, dst
);
2802 if (!m_defaultClause
)
2803 generator
.emitLabel(defaultLabel
.get());
2805 ASSERT(i
== labelVector
.size());
2806 if (switchType
!= SwitchInfo::SwitchNone
) {
2807 ASSERT(labelVector
.size() == literalVector
.size());
2808 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
2812 // ------------------------------ SwitchNode -----------------------------------
2814 void SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2816 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2818 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::Switch
);
2820 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
2821 m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
2823 generator
.emitLabel(scope
->breakTarget());
2824 generator
.emitProfileControlFlow(endOffset());
2827 // ------------------------------ LabelNode ------------------------------------
2829 void LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2831 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2833 ASSERT(!generator
.breakTarget(m_name
));
2835 LabelScopePtr scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
2836 generator
.emitNode(dst
, m_statement
);
2838 generator
.emitLabel(scope
->breakTarget());
2841 // ------------------------------ ThrowNode ------------------------------------
2843 void ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2845 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2847 if (dst
== generator
.ignoredResult())
2849 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
2850 generator
.emitExpressionInfo(divot(), divotStart(), divotEnd());
2851 generator
.emitThrow(expr
.get());
2853 generator
.emitProfileControlFlow(endOffset());
2856 // ------------------------------ TryNode --------------------------------------
2858 void TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2860 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2861 // optimizer knows they may be jumped to from anywhere.
2863 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), startOffset(), lineStartOffset());
2865 ASSERT(m_catchBlock
|| m_finallyBlock
);
2867 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
2868 generator
.emitLabel(tryStartLabel
.get());
2871 generator
.pushFinallyContext(m_finallyBlock
);
2872 TryData
* tryData
= generator
.pushTry(tryStartLabel
.get());
2874 generator
.emitNode(dst
, m_tryBlock
);
2877 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
2879 // Normal path: jump over the catch block.
2880 generator
.emitJump(catchEndLabel
.get());
2882 // Uncaught exception path: the catch block.
2883 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
2884 RefPtr
<RegisterID
> exceptionRegister
= generator
.newTemporary();
2885 RefPtr
<RegisterID
> thrownValueRegister
= generator
.newTemporary();
2886 generator
.popTryAndEmitCatch(tryData
, exceptionRegister
.get(), thrownValueRegister
.get(), here
.get(), HandlerType::Catch
);
2888 if (m_finallyBlock
) {
2889 // If the catch block throws an exception and we have a finally block, then the finally
2890 // block should "catch" that exception.
2891 tryData
= generator
.pushTry(here
.get());
2894 generator
.emitPushCatchScope(generator
.scopeRegister(), m_thrownValueIdent
, thrownValueRegister
.get(), DontDelete
);
2895 generator
.emitProfileControlFlow(m_tryBlock
->endOffset() + 1);
2896 generator
.emitNode(dst
, m_catchBlock
);
2897 generator
.emitPopScope(generator
.scopeRegister());
2898 generator
.emitLabel(catchEndLabel
.get());
2901 if (m_finallyBlock
) {
2902 RefPtr
<Label
> preFinallyLabel
= generator
.emitLabel(generator
.newLabel().get());
2904 generator
.popFinallyContext();
2906 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
2908 int finallyStartOffset
= m_catchBlock
? m_catchBlock
->endOffset() + 1 : m_tryBlock
->endOffset() + 1;
2910 // Normal path: run the finally code, and jump to the end.
2911 generator
.emitProfileControlFlow(finallyStartOffset
);
2912 generator
.emitNode(dst
, m_finallyBlock
);
2913 generator
.emitProfileControlFlow(m_finallyBlock
->endOffset() + 1);
2914 generator
.emitJump(finallyEndLabel
.get());
2916 // Uncaught exception path: invoke the finally block, then re-throw the exception.
2917 RefPtr
<RegisterID
> exceptionRegister
= generator
.newTemporary();
2918 RefPtr
<RegisterID
> thrownValueRegister
= generator
.newTemporary();
2919 generator
.popTryAndEmitCatch(tryData
, exceptionRegister
.get(), thrownValueRegister
.get(), preFinallyLabel
.get(), HandlerType::Finally
);
2920 generator
.emitProfileControlFlow(finallyStartOffset
);
2921 generator
.emitNode(dst
, m_finallyBlock
);
2922 generator
.emitThrow(exceptionRegister
.get());
2924 generator
.emitLabel(finallyEndLabel
.get());
2925 generator
.emitProfileControlFlow(m_finallyBlock
->endOffset() + 1);
2927 generator
.emitProfileControlFlow(m_catchBlock
->endOffset() + 1);
2931 // ------------------------------ ScopeNode -----------------------------
2933 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2937 m_statements
->emitBytecode(generator
, dst
);
2940 // ------------------------------ ProgramNode -----------------------------
2942 void ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2944 generator
.emitDebugHook(WillExecuteProgram
, startLine(), startStartOffset(), startLineStartOffset());
2946 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
2947 generator
.emitLoad(dstRegister
.get(), jsUndefined());
2948 generator
.emitProfileControlFlow(startStartOffset());
2949 emitStatementsBytecode(generator
, dstRegister
.get());
2951 generator
.emitDebugHook(DidExecuteProgram
, lastLine(), startOffset(), lineStartOffset());
2952 generator
.emitEnd(dstRegister
.get());
2955 // ------------------------------ EvalNode -----------------------------
2957 void EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2959 generator
.emitDebugHook(WillExecuteProgram
, startLine(), startStartOffset(), startLineStartOffset());
2961 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
2962 generator
.emitLoad(dstRegister
.get(), jsUndefined());
2963 emitStatementsBytecode(generator
, dstRegister
.get());
2965 generator
.emitDebugHook(DidExecuteProgram
, lastLine(), startOffset(), lineStartOffset());
2966 generator
.emitEnd(dstRegister
.get());
2969 // ------------------------------ FunctionBodyNode -----------------------------
2971 void FunctionBodyNode::emitBytecode(BytecodeGenerator
&, RegisterID
*)
2975 void FunctionNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2977 if (generator
.vm()->typeProfiler()) {
2978 for (size_t i
= 0; i
< m_parameters
->size(); i
++) {
2979 // FIXME: Handle Destructuring assignments into arguments.
2980 if (!m_parameters
->at(i
)->isBindingNode())
2982 BindingNode
* parameter
= static_cast<BindingNode
*>(m_parameters
->at(i
));
2983 RegisterID
reg(CallFrame::argumentOffset(i
));
2984 generator
.emitProfileType(®
, ProfileTypeBytecodeFunctionArgument
, nullptr);
2985 generator
.emitTypeProfilerExpressionInfo(parameter
->divotStart(), parameter
->divotEnd());
2989 generator
.emitProfileControlFlow(startStartOffset());
2990 generator
.emitDebugHook(DidEnterCallFrame
, startLine(), startStartOffset(), startLineStartOffset());
2991 emitStatementsBytecode(generator
, generator
.ignoredResult());
2993 StatementNode
* singleStatement
= this->singleStatement();
2994 ReturnNode
* returnNode
= 0;
2996 // Check for a return statement at the end of a function composed of a single block.
2997 if (singleStatement
&& singleStatement
->isBlock()) {
2998 StatementNode
* lastStatementInBlock
= static_cast<BlockNode
*>(singleStatement
)->lastStatement();
2999 if (lastStatementInBlock
&& lastStatementInBlock
->isReturnNode())
3000 returnNode
= static_cast<ReturnNode
*>(lastStatementInBlock
);
3003 // If there is no return we must automatically insert one.
3005 RegisterID
* r0
= generator
.isConstructor() ? generator
.thisRegister() : generator
.emitLoad(0, jsUndefined());
3006 if (generator
.vm()->typeProfiler())
3007 generator
.emitProfileType(r0
, ProfileTypeBytecodeFunctionReturnStatement
, nullptr); // Do not emit expression info for this profile because it's not in the user's source code.
3008 ASSERT(startOffset() >= lineStartOffset());
3009 generator
.emitDebugHook(WillLeaveCallFrame
, lastLine(), startOffset(), lineStartOffset());
3010 generator
.emitReturn(r0
);
3015 // ------------------------------ FuncDeclNode ---------------------------------
3017 void FuncDeclNode::emitBytecode(BytecodeGenerator
&, RegisterID
*)
3021 // ------------------------------ FuncExprNode ---------------------------------
3023 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
3025 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);
3028 #if ENABLE(ES6_CLASS_SYNTAX)
3029 // ------------------------------ ClassDeclNode ---------------------------------
3031 void ClassDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
3033 generator
.emitNode(dst
, m_classDeclaration
);
3036 // ------------------------------ ClassExprNode ---------------------------------
3038 RegisterID
* ClassExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
3040 RefPtr
<RegisterID
> superclass
;
3041 if (m_classHeritage
) {
3042 superclass
= generator
.newTemporary();
3043 generator
.emitNode(superclass
.get(), m_classHeritage
);
3046 RefPtr
<RegisterID
> constructor
;
3048 // FIXME: Make the prototype non-configurable & non-writable.
3049 if (m_constructorExpression
)
3050 constructor
= generator
.emitNode(dst
, m_constructorExpression
);
3052 constructor
= generator
.emitNewDefaultConstructor(generator
.finalDestination(dst
),
3053 m_classHeritage
? ConstructorKind::Derived
: ConstructorKind::Base
, m_name
);
3056 const auto& propertyNames
= generator
.propertyNames();
3057 RefPtr
<RegisterID
> prototype
= generator
.emitNewObject(generator
.newTemporary());
3060 RefPtr
<RegisterID
> protoParent
= generator
.newTemporary();
3061 generator
.emitLoad(protoParent
.get(), jsNull());
3063 RefPtr
<RegisterID
> tempRegister
= generator
.newTemporary();
3065 // FIXME: Throw TypeError if it's a generator function.
3066 RefPtr
<Label
> superclassIsUndefinedLabel
= generator
.newLabel();
3067 generator
.emitJumpIfTrue(generator
.emitIsUndefined(tempRegister
.get(), superclass
.get()), superclassIsUndefinedLabel
.get());
3069 RefPtr
<Label
> superclassIsNullLabel
= generator
.newLabel();
3070 generator
.emitJumpIfTrue(generator
.emitUnaryOp(op_eq_null
, tempRegister
.get(), superclass
.get()), superclassIsNullLabel
.get());
3072 RefPtr
<Label
> superclassIsObjectLabel
= generator
.newLabel();
3073 generator
.emitJumpIfTrue(generator
.emitIsObject(tempRegister
.get(), superclass
.get()), superclassIsObjectLabel
.get());
3074 generator
.emitLabel(superclassIsUndefinedLabel
.get());
3075 generator
.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3076 generator
.emitLabel(superclassIsObjectLabel
.get());
3077 generator
.emitGetById(protoParent
.get(), superclass
.get(), generator
.propertyNames().prototype
);
3079 RefPtr
<Label
> protoParentIsObjectOrNullLabel
= generator
.newLabel();
3080 generator
.emitJumpIfTrue(generator
.emitUnaryOp(op_is_object_or_null
, tempRegister
.get(), protoParent
.get()), protoParentIsObjectOrNullLabel
.get());
3081 generator
.emitThrowTypeError(ASCIILiteral("The superclass's prototype is not an object."));
3082 generator
.emitLabel(protoParentIsObjectOrNullLabel
.get());
3084 generator
.emitDirectPutById(constructor
.get(), generator
.propertyNames().underscoreProto
, superclass
.get(), PropertyNode::Unknown
);
3085 generator
.emitLabel(superclassIsNullLabel
.get());
3086 generator
.emitDirectPutById(prototype
.get(), generator
.propertyNames().underscoreProto
, protoParent
.get(), PropertyNode::Unknown
);
3088 emitPutHomeObject(generator
, constructor
.get(), prototype
.get());
3091 RefPtr
<RegisterID
> constructorNameRegister
= generator
.emitLoad(generator
.newTemporary(), propertyNames
.constructor
);
3092 generator
.emitCallDefineProperty(prototype
.get(), constructorNameRegister
.get(), constructor
.get(), nullptr, nullptr,
3093 BytecodeGenerator::PropertyConfigurable
| BytecodeGenerator::PropertyWritable
, m_position
);
3095 RefPtr
<RegisterID
> prototypeNameRegister
= generator
.emitLoad(generator
.newTemporary(), propertyNames
.prototype
);
3096 generator
.emitCallDefineProperty(constructor
.get(), prototypeNameRegister
.get(), prototype
.get(), nullptr, nullptr, 0, m_position
);
3098 if (m_staticMethods
)
3099 generator
.emitNode(constructor
.get(), m_staticMethods
);
3101 if (m_instanceMethods
)
3102 generator
.emitNode(prototype
.get(), m_instanceMethods
);
3104 return generator
.moveToDestinationIfNeeded(dst
, constructor
.get());
3108 // ------------------------------ DestructuringAssignmentNode -----------------
3109 RegisterID
* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
3111 if (RegisterID
* result
= m_bindings
->emitDirectBinding(generator
, dst
, m_initializer
))
3113 RefPtr
<RegisterID
> initializer
= generator
.tempDestination(dst
);
3114 generator
.emitNode(initializer
.get(), m_initializer
);
3115 m_bindings
->bindValue(generator
, initializer
.get());
3116 return generator
.moveToDestinationIfNeeded(dst
, initializer
.get());
3119 DestructuringPatternNode::~DestructuringPatternNode()
3123 static void assignDefaultValueIfUndefined(BytecodeGenerator
& generator
, RegisterID
* maybeUndefined
, ExpressionNode
* defaultValue
)
3125 ASSERT(defaultValue
);
3126 RefPtr
<Label
> isNotUndefined
= generator
.newLabel();
3127 generator
.emitJumpIfFalse(generator
.emitIsUndefined(generator
.newTemporary(), maybeUndefined
), isNotUndefined
.get());
3128 generator
.emitNode(maybeUndefined
, defaultValue
);
3129 generator
.emitLabel(isNotUndefined
.get());
3132 void ArrayPatternNode::bindValue(BytecodeGenerator
& generator
, RegisterID
* rhs
) const
3134 RefPtr
<RegisterID
> iterator
= generator
.newTemporary();
3136 generator
.emitGetById(iterator
.get(), rhs
, generator
.propertyNames().iteratorSymbol
);
3137 CallArguments
args(generator
, nullptr);
3138 generator
.emitMove(args
.thisRegister(), rhs
);
3139 generator
.emitCall(iterator
.get(), iterator
.get(), NoExpectedFunction
, args
, divot(), divotStart(), divotEnd());
3142 if (m_targetPatterns
.isEmpty()) {
3143 generator
.emitIteratorClose(iterator
.get(), this);
3147 RefPtr
<RegisterID
> done
;
3148 for (auto& target
: m_targetPatterns
) {
3149 switch (target
.bindingType
) {
3150 case BindingType::Elision
:
3151 case BindingType::Element
: {
3152 RefPtr
<Label
> iterationSkipped
= generator
.newLabel();
3154 done
= generator
.newTemporary();
3156 generator
.emitJumpIfTrue(done
.get(), iterationSkipped
.get());
3158 RefPtr
<RegisterID
> value
= generator
.newTemporary();
3159 generator
.emitIteratorNext(value
.get(), iterator
.get(), this);
3160 generator
.emitGetById(done
.get(), value
.get(), generator
.propertyNames().done
);
3161 generator
.emitJumpIfTrue(done
.get(), iterationSkipped
.get());
3162 generator
.emitGetById(value
.get(), value
.get(), generator
.propertyNames().value
);
3165 RefPtr
<Label
> valueIsSet
= generator
.newLabel();
3166 generator
.emitJump(valueIsSet
.get());
3167 generator
.emitLabel(iterationSkipped
.get());
3168 generator
.emitLoad(value
.get(), jsUndefined());
3169 generator
.emitLabel(valueIsSet
.get());
3172 if (target
.bindingType
== BindingType::Element
) {
3173 if (target
.defaultValue
)
3174 assignDefaultValueIfUndefined(generator
, value
.get(), target
.defaultValue
);
3175 target
.pattern
->bindValue(generator
, value
.get());
3180 case BindingType::RestElement
: {
3181 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.newTemporary(), 0, 0);
3183 RefPtr
<Label
> iterationDone
= generator
.newLabel();
3185 done
= generator
.newTemporary();
3187 generator
.emitJumpIfTrue(done
.get(), iterationDone
.get());
3189 RefPtr
<RegisterID
> index
= generator
.newTemporary();
3190 generator
.emitLoad(index
.get(), jsNumber(0));
3191 RefPtr
<Label
> loopStart
= generator
.newLabel();
3192 generator
.emitLabel(loopStart
.get());
3194 RefPtr
<RegisterID
> value
= generator
.newTemporary();
3195 generator
.emitIteratorNext(value
.get(), iterator
.get(), this);
3196 generator
.emitGetById(done
.get(), value
.get(), generator
.propertyNames().done
);
3197 generator
.emitJumpIfTrue(done
.get(), iterationDone
.get());
3198 generator
.emitGetById(value
.get(), value
.get(), generator
.propertyNames().value
);
3200 generator
.emitDirectPutByVal(array
.get(), index
.get(), value
.get());
3201 generator
.emitInc(index
.get());
3202 generator
.emitJump(loopStart
.get());
3204 generator
.emitLabel(iterationDone
.get());
3205 target
.pattern
->bindValue(generator
, array
.get());
3211 RefPtr
<Label
> iteratorClosed
= generator
.newLabel();
3212 generator
.emitJumpIfTrue(done
.get(), iteratorClosed
.get());
3213 generator
.emitIteratorClose(iterator
.get(), this);
3214 generator
.emitLabel(iteratorClosed
.get());
3217 RegisterID
* ArrayPatternNode::emitDirectBinding(BytecodeGenerator
& generator
, RegisterID
* dst
, ExpressionNode
* rhs
)
3219 if (!rhs
->isSimpleArray())
3222 RefPtr
<RegisterID
> resultRegister
;
3223 if (dst
&& dst
!= generator
.ignoredResult())
3224 resultRegister
= generator
.emitNewArray(generator
.newTemporary(), 0, 0);
3225 ElementNode
* elementNodes
= static_cast<ArrayNode
*>(rhs
)->elements();
3226 Vector
<ExpressionNode
*> elements
;
3227 for (; elementNodes
; elementNodes
= elementNodes
->next())
3228 elements
.append(elementNodes
->value());
3229 if (m_targetPatterns
.size() != elements
.size())
3231 Vector
<RefPtr
<RegisterID
>> registers
;
3232 registers
.reserveCapacity(m_targetPatterns
.size());
3233 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
3234 registers
.uncheckedAppend(generator
.newTemporary());
3235 generator
.emitNode(registers
.last().get(), elements
[i
]);
3236 if (m_targetPatterns
[i
].defaultValue
)
3237 assignDefaultValueIfUndefined(generator
, registers
.last().get(), m_targetPatterns
[i
].defaultValue
);
3239 generator
.emitPutByIndex(resultRegister
.get(), i
, registers
.last().get());
3242 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
3243 if (m_targetPatterns
[i
].pattern
)
3244 m_targetPatterns
[i
].pattern
->bindValue(generator
, registers
[i
].get());
3247 return generator
.moveToDestinationIfNeeded(dst
, resultRegister
.get());
3248 return generator
.emitLoad(generator
.finalDestination(dst
), jsUndefined());
3251 void ArrayPatternNode::toString(StringBuilder
& builder
) const
3253 builder
.append('[');
3254 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
3255 const auto& target
= m_targetPatterns
[i
];
3257 switch (target
.bindingType
) {
3258 case BindingType::Elision
:
3259 builder
.append(',');
3262 case BindingType::Element
:
3263 target
.pattern
->toString(builder
);
3264 if (i
< m_targetPatterns
.size() - 1)
3265 builder
.append(',');
3268 case BindingType::RestElement
:
3269 builder
.append("...");
3270 target
.pattern
->toString(builder
);
3274 builder
.append(']');
3277 void ArrayPatternNode::collectBoundIdentifiers(Vector
<Identifier
>& identifiers
) const
3279 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
3280 if (DestructuringPatternNode
* node
= m_targetPatterns
[i
].pattern
.get())
3281 node
->collectBoundIdentifiers(identifiers
);
3285 void ObjectPatternNode::toString(StringBuilder
& builder
) const
3287 builder
.append('{');
3288 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
3289 if (m_targetPatterns
[i
].wasString
)
3290 builder
.appendQuotedJSONString(m_targetPatterns
[i
].propertyName
.string());
3292 builder
.append(m_targetPatterns
[i
].propertyName
.string());
3293 builder
.append(':');
3294 m_targetPatterns
[i
].pattern
->toString(builder
);
3295 if (i
< m_targetPatterns
.size() - 1)
3296 builder
.append(',');
3298 builder
.append('}');
3301 void ObjectPatternNode::bindValue(BytecodeGenerator
& generator
, RegisterID
* rhs
) const
3303 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++) {
3304 auto& target
= m_targetPatterns
[i
];
3305 RefPtr
<RegisterID
> temp
= generator
.newTemporary();
3306 generator
.emitGetById(temp
.get(), rhs
, target
.propertyName
);
3307 if (target
.defaultValue
)
3308 assignDefaultValueIfUndefined(generator
, temp
.get(), target
.defaultValue
);
3309 target
.pattern
->bindValue(generator
, temp
.get());
3313 void ObjectPatternNode::collectBoundIdentifiers(Vector
<Identifier
>& identifiers
) const
3315 for (size_t i
= 0; i
< m_targetPatterns
.size(); i
++)
3316 m_targetPatterns
[i
].pattern
->collectBoundIdentifiers(identifiers
);
3319 void BindingNode::bindValue(BytecodeGenerator
& generator
, RegisterID
* value
) const
3321 Variable var
= generator
.variable(m_boundProperty
);
3322 if (RegisterID
* local
= var
.local()) {
3323 if (var
.isReadOnly()) {
3324 generator
.emitReadOnlyExceptionIfNeeded();
3327 generator
.emitMove(local
, value
);
3328 if (generator
.vm()->typeProfiler())
3329 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
3332 if (generator
.isStrictMode())
3333 generator
.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3334 RegisterID
* scope
= generator
.emitResolveScope(nullptr, var
);
3335 generator
.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3336 generator
.emitPutToScope(scope
, var
, value
, generator
.isStrictMode() ? ThrowIfNotFound
: DoNotThrowIfNotFound
);
3337 if (generator
.vm()->typeProfiler()) {
3338 generator
.emitProfileType(value
, var
.isResolved() ? ProfileTypeBytecodePutToLocalScope
: ProfileTypeBytecodePutToScope
, &m_boundProperty
);
3339 generator
.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
3344 void BindingNode::toString(StringBuilder
& builder
) const
3346 builder
.append(m_boundProperty
.string());
3349 void BindingNode::collectBoundIdentifiers(Vector
<Identifier
>& identifiers
) const
3351 identifiers
.append(m_boundProperty
);
3354 RegisterID
* SpreadExpressionNode::emitBytecode(BytecodeGenerator
&, RegisterID
*)
3356 RELEASE_ASSERT_NOT_REACHED();