1/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
4* Copyright (C) 2003-2019 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.
9*
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.
14*
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.
19*
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.
24*
25*/
26
27#include "config.h"
28#include "Nodes.h"
29#include "NodeConstructors.h"
30
31#include "BuiltinNames.h"
32#include "BytecodeGenerator.h"
33#include "CallFrame.h"
34#include "JIT.h"
35#include "JSCInlines.h"
36#include "JSFunction.h"
37#include "JSGeneratorFunction.h"
38#include "JSGlobalObject.h"
39#include "JSImmutableButterfly.h"
40#include "LabelScope.h"
41#include "Lexer.h"
42#include "Parser.h"
43#include "StackAlignment.h"
44#include "UnlinkedMetadataTableInlines.h"
45#include "YarrFlags.h"
46#include <wtf/Assertions.h>
47#include <wtf/Threading.h>
48#include <wtf/text/StringBuilder.h>
49
50namespace JSC {
51
52/*
53 Details of the emitBytecode function.
54
55 Return value: The register holding the production's value.
56 dst: An optional parameter specifying the most efficient destination at
57 which to store the production's value. The callee must honor dst.
58
59 The dst argument provides for a crude form of copy propagation. For example,
60
61 x = 1
62
63 becomes
64
65 load r[x], 1
66
67 instead of
68
69 load r0, 1
70 mov r[x], r0
71
72 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
73*/
74
75void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
76{
77 RegisterID* result = generator.emitNode(this);
78 if (fallThroughMode == FallThroughMeansTrue)
79 generator.emitJumpIfFalse(result, falseTarget);
80 else
81 generator.emitJumpIfTrue(result, trueTarget);
82}
83
84// ------------------------------ ThrowableExpressionData --------------------------------
85
86RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
87{
88 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
89 generator.emitThrowReferenceError(message);
90 return generator.newTemporary();
91}
92
93// ------------------------------ ConstantNode ----------------------------------
94
95void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
96{
97 TriState value = jsValue(generator).pureToBoolean();
98
99 if (UNLIKELY(needsDebugHook())) {
100 if (value != MixedTriState)
101 generator.emitDebugHook(this);
102 }
103
104 if (value == MixedTriState)
105 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
106 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
107 generator.emitJump(trueTarget);
108 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
109 generator.emitJump(falseTarget);
110
111 // All other cases are unconditional fall-throughs, like "if (true)".
112}
113
114RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
115{
116 if (dst == generator.ignoredResult())
117 return 0;
118 return generator.emitLoad(dst, jsValue(generator));
119}
120
121JSValue StringNode::jsValue(BytecodeGenerator& generator) const
122{
123 return generator.addStringConstant(m_value);
124}
125
126JSValue BigIntNode::jsValue(BytecodeGenerator& generator) const
127{
128 return generator.addBigIntConstant(m_value, m_radix, m_sign);
129}
130
131// ------------------------------ NumberNode ----------------------------------
132
133RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
134{
135 if (dst == generator.ignoredResult())
136 return nullptr;
137 return generator.emitLoad(dst, jsValue(generator), isIntegerNode() ? SourceCodeRepresentation::Integer : SourceCodeRepresentation::Double);
138}
139
140// ------------------------------ RegExpNode -----------------------------------
141
142RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
143{
144 if (dst == generator.ignoredResult())
145 return nullptr;
146
147 auto flags = Yarr::parseFlags(m_flags.string());
148 ASSERT(flags.hasValue());
149 RegExp* regExp = RegExp::create(*generator.vm(), m_pattern.string(), flags.value());
150 if (regExp->isValid())
151 return generator.emitNewRegExp(generator.finalDestination(dst), regExp);
152
153 const char* messageCharacters = regExp->errorMessage();
154 const Identifier& message = generator.parserArena().identifierArena().makeIdentifier(generator.vm(), bitwise_cast<const LChar*>(messageCharacters), strlen(messageCharacters));
155 generator.emitThrowStaticError(ErrorType::SyntaxError, message);
156 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
157}
158
159// ------------------------------ ThisNode -------------------------------------
160
161RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
162{
163 generator.ensureThis();
164 if (dst == generator.ignoredResult())
165 return 0;
166
167 RegisterID* result = generator.move(dst, generator.thisRegister());
168 static const unsigned thisLength = 4;
169 generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
170 return result;
171}
172
173// ------------------------------ SuperNode -------------------------------------
174
175static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator)
176{
177 if (generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {
178 RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
179 return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().builtinNames().homeObjectPrivateName());
180 }
181
182 RegisterID callee;
183 callee.setIndex(CallFrameSlot::callee);
184 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().builtinNames().homeObjectPrivateName());
185}
186
187static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
188{
189 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
190 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
191}
192
193static RegisterID* emitGetSuperFunctionForConstruct(BytecodeGenerator& generator)
194{
195 if (generator.isDerivedConstructorContext())
196 return generator.emitGetById(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(), generator.propertyNames().underscoreProto);
197
198 RegisterID callee;
199 callee.setIndex(CallFrameSlot::callee);
200 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().underscoreProto);
201}
202
203RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
204{
205 RegisterID* result = emitSuperBaseForCallee(generator);
206 return generator.move(generator.finalDestination(dst), result);
207}
208
209// ------------------------------ ImportNode -------------------------------------
210
211RegisterID* ImportNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
212{
213 RefPtr<RegisterID> importModule = generator.emitGetGlobalPrivate(generator.newTemporary(), generator.propertyNames().builtinNames().importModulePrivateName());
214 CallArguments arguments(generator, nullptr, 1);
215 generator.emitLoad(arguments.thisRegister(), jsUndefined());
216 generator.emitNode(arguments.argumentRegister(0), m_expr);
217 return generator.emitCall(generator.finalDestination(dst, importModule.get()), importModule.get(), NoExpectedFunction, arguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
218}
219
220// ------------------------------ NewTargetNode ----------------------------------
221
222RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
223{
224 if (dst == generator.ignoredResult())
225 return nullptr;
226
227 return generator.move(dst, generator.newTarget());
228}
229
230// ------------------------------ ImportMetaNode ---------------------------------
231
232RegisterID* ImportMetaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
233{
234 return generator.emitNode(dst, m_expr);
235}
236
237// ------------------------------ ResolveNode ----------------------------------
238
239bool ResolveNode::isPure(BytecodeGenerator& generator) const
240{
241 return generator.variable(m_ident).offset().isStack();
242}
243
244RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
245{
246 Variable var = generator.variable(m_ident);
247 if (RegisterID* local = var.local()) {
248 generator.emitTDZCheckIfNecessary(var, local, nullptr);
249 if (dst == generator.ignoredResult())
250 return nullptr;
251
252 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
253 return generator.move(dst, local);
254 }
255
256 JSTextPosition divot = m_start + m_ident.length();
257 generator.emitExpressionInfo(divot, m_start, divot);
258 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
259 RegisterID* finalDest = generator.finalDestination(dst);
260 RefPtr<RegisterID> uncheckedResult = generator.newTemporary();
261 generator.emitGetFromScope(uncheckedResult.get(), scope.get(), var, ThrowIfNotFound);
262 generator.emitTDZCheckIfNecessary(var, uncheckedResult.get(), nullptr);
263 generator.move(finalDest, uncheckedResult.get());
264 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
265 return finalDest;
266}
267
268// ------------------------------ TemplateStringNode -----------------------------------
269
270RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
271{
272 if (dst == generator.ignoredResult())
273 return nullptr;
274 ASSERT(cooked());
275 return generator.emitLoad(dst, JSValue(generator.addStringConstant(*cooked())));
276}
277
278// ------------------------------ TemplateLiteralNode -----------------------------------
279
280RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
281{
282 if (!m_templateExpressions) {
283 TemplateStringNode* templateString = m_templateStrings->value();
284 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
285 return generator.emitNode(dst, templateString);
286 }
287
288 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
289
290 TemplateStringListNode* templateString = m_templateStrings;
291 TemplateExpressionListNode* templateExpression = m_templateExpressions;
292 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
293 // Evaluate TemplateString.
294 ASSERT(templateString->value()->cooked());
295 if (!templateString->value()->cooked()->isEmpty()) {
296 temporaryRegisters.append(generator.newTemporary());
297 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
298 }
299
300 // Evaluate Expression.
301 temporaryRegisters.append(generator.newTemporary());
302 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
303 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
304 }
305
306 // Evaluate tail TemplateString.
307 ASSERT(templateString->value()->cooked());
308 if (!templateString->value()->cooked()->isEmpty()) {
309 temporaryRegisters.append(generator.newTemporary());
310 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
311 }
312
313 if (temporaryRegisters.size() == 1)
314 return generator.emitToString(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get());
315
316 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
317}
318
319// ------------------------------ TaggedTemplateNode -----------------------------------
320
321RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
322{
323 ExpectedFunction expectedFunction = NoExpectedFunction;
324 RefPtr<RegisterID> tag = nullptr;
325 RefPtr<RegisterID> base = nullptr;
326 if (!m_tag->isLocation()) {
327 tag = generator.newTemporary();
328 tag = generator.emitNode(tag.get(), m_tag);
329 } else if (m_tag->isResolveNode()) {
330 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
331 const Identifier& identifier = resolve->identifier();
332 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
333
334 Variable var = generator.variable(identifier);
335 if (RegisterID* local = var.local()) {
336 generator.emitTDZCheckIfNecessary(var, local, nullptr);
337 tag = generator.move(generator.newTemporary(), local);
338 } else {
339 tag = generator.newTemporary();
340 base = generator.newTemporary();
341
342 JSTextPosition newDivot = divotStart() + identifier.length();
343 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
344 generator.move(base.get(), generator.emitResolveScope(base.get(), var));
345 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
346 generator.emitTDZCheckIfNecessary(var, tag.get(), nullptr);
347 }
348 } else if (m_tag->isBracketAccessorNode()) {
349 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
350 base = generator.newTemporary();
351 base = generator.emitNode(base.get(), bracket->base());
352 RefPtr<RegisterID> property = generator.emitNodeForProperty(bracket->subscript());
353 if (bracket->base()->isSuperNode()) {
354 RefPtr<RegisterID> thisValue = generator.ensureThis();
355 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
356 } else
357 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
358 } else {
359 ASSERT(m_tag->isDotAccessorNode());
360 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
361 base = generator.newTemporary();
362 base = generator.emitNode(base.get(), dot->base());
363 if (dot->base()->isSuperNode()) {
364 RefPtr<RegisterID> thisValue = generator.ensureThis();
365 tag = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), dot->identifier());
366 } else
367 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
368 }
369
370 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(nullptr, this);
371
372 unsigned expressionsCount = 0;
373 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
374 ++expressionsCount;
375
376 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
377 if (base)
378 generator.move(callArguments.thisRegister(), base.get());
379 else
380 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
381
382 unsigned argumentIndex = 0;
383 generator.move(callArguments.argumentRegister(argumentIndex++), templateObject.get());
384 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
385 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
386
387 return generator.emitCallInTailPosition(generator.finalDestination(dst, tag.get()), tag.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
388}
389
390// ------------------------------ ArrayNode ------------------------------------
391
392RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
393{
394 bool hadVariableExpression = false;
395 unsigned length = 0;
396
397 IndexingType recommendedIndexingType = ArrayWithUndecided;
398 ElementNode* firstPutElement;
399 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
400 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
401 break;
402 if (!firstPutElement->value()->isConstant())
403 hadVariableExpression = true;
404 else
405 recommendedIndexingType = leastUpperBoundOfIndexingTypeAndValue(recommendedIndexingType, static_cast<ConstantNode*>(firstPutElement->value())->jsValue(generator));
406
407 ++length;
408 }
409
410 auto newArray = [&] (RegisterID* dst, ElementNode* elements, unsigned length, bool hadVariableExpression) {
411 if (length && !hadVariableExpression) {
412 recommendedIndexingType |= CopyOnWrite;
413 ASSERT(generator.vm()->heap.isDeferred()); // We run bytecode generator under a DeferGC. If we stopped doing that, we'd need to put a DeferGC here as we filled in these slots.
414 auto* array = JSImmutableButterfly::create(*generator.vm(), recommendedIndexingType, length);
415 unsigned index = 0;
416 for (ElementNode* element = elements; index < length; element = element->next()) {
417 ASSERT(element->value()->isConstant());
418 array->setIndex(*generator.vm(), index++, static_cast<ConstantNode*>(element->value())->jsValue(generator));
419 }
420 return generator.emitNewArrayBuffer(dst, array, recommendedIndexingType);
421 }
422 return generator.emitNewArray(dst, elements, length, recommendedIndexingType);
423 };
424
425 if (!firstPutElement && !m_elision)
426 return newArray(generator.finalDestination(dst), m_element, length, hadVariableExpression);
427
428 if (firstPutElement && firstPutElement->value()->isSpreadExpression()) {
429 bool hasElision = m_elision;
430 if (!hasElision) {
431 for (ElementNode* node = firstPutElement; node; node = node->next()) {
432 if (node->elision()) {
433 hasElision = true;
434 break;
435 }
436 }
437 }
438
439 if (!hasElision)
440 return generator.emitNewArrayWithSpread(generator.finalDestination(dst), m_element);
441 }
442
443 RefPtr<RegisterID> array = newArray(generator.tempDestination(dst), m_element, length, hadVariableExpression);
444 ElementNode* n = firstPutElement;
445 for (; n; n = n->next()) {
446 if (n->value()->isSpreadExpression())
447 goto handleSpread;
448 RefPtr<RegisterID> value = generator.emitNode(n->value());
449 length += n->elision();
450
451 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(length++));
452 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
453 }
454
455 if (m_elision) {
456 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
457 generator.emitPutById(array.get(), generator.propertyNames().length, value);
458 }
459
460 return generator.move(dst, array.get());
461
462handleSpread:
463 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
464 auto spreader = scopedLambda<void(BytecodeGenerator&, RegisterID*)>([array, index](BytecodeGenerator& generator, RegisterID* value)
465 {
466 generator.emitDirectPutByVal(array.get(), index.get(), value);
467 generator.emitInc(index.get());
468 });
469 for (; n; n = n->next()) {
470 if (n->elision())
471 generator.emitBinaryOp<OpAdd>(index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
472 if (n->value()->isSpreadExpression()) {
473 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
474 generator.emitEnumeration(spread, spread->expression(), spreader);
475 } else {
476 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
477 generator.emitInc(index.get());
478 }
479 }
480
481 if (m_elision) {
482 generator.emitBinaryOp<OpAdd>(index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
483 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
484 }
485 return generator.move(dst, array.get());
486}
487
488bool ArrayNode::isSimpleArray() const
489{
490 if (m_elision || m_optional)
491 return false;
492 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
493 if (ptr->elision())
494 return false;
495 if (ptr->value()->isSpreadExpression())
496 return false;
497 }
498 return true;
499}
500
501ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
502{
503 ASSERT(!m_elision && !m_optional);
504 ElementNode* ptr = m_element;
505 if (!ptr)
506 return 0;
507 JSTokenLocation location;
508 location.line = lineNumber;
509 location.startOffset = startPosition;
510 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
511 ArgumentListNode* tail = head;
512 ptr = ptr->next();
513 for (; ptr; ptr = ptr->next()) {
514 ASSERT(!ptr->elision());
515 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
516 }
517 return head;
518}
519
520// ------------------------------ ObjectLiteralNode ----------------------------
521
522RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
523{
524 if (!m_list) {
525 if (dst == generator.ignoredResult())
526 return 0;
527 return generator.emitNewObject(generator.finalDestination(dst));
528 }
529 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
530 generator.emitNode(newObj.get(), m_list);
531 return generator.move(dst, newObj.get());
532}
533
534// ------------------------------ PropertyListNode -----------------------------
535
536static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
537{
538 generator.emitPutById(function, generator.propertyNames().builtinNames().homeObjectPrivateName(), homeObject);
539}
540
541RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dstOrConstructor, RegisterID* prototype)
542{
543 // Fast case: this loop just handles regular value properties.
544 PropertyListNode* p = this;
545 RegisterID* dst = nullptr;
546 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next) {
547 dst = p->m_node->isInstanceClassProperty() ? prototype : dstOrConstructor;
548 emitPutConstantProperty(generator, dst, *p->m_node);
549 }
550
551 // Were there any get/set properties?
552 if (p) {
553 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
554 // a computed property or a spread, just emit everything as that may override previous values.
555 bool canOverrideProperties = false;
556
557 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
558 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
559 GetterSetterMap instanceMap;
560 GetterSetterMap staticMap;
561
562 // Build a map, pairing get/set values together.
563 for (PropertyListNode* q = p; q; q = q->m_next) {
564 PropertyNode* node = q->m_node;
565 if (node->m_type & PropertyNode::Computed || node->m_type & PropertyNode::Spread) {
566 canOverrideProperties = true;
567 break;
568 }
569
570 if (node->m_type & PropertyNode::Constant)
571 continue;
572
573 // Duplicates are possible.
574 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
575 GetterSetterMap& map = node->isStaticClassProperty() ? staticMap : instanceMap;
576 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
577 auto& resultPair = result.iterator->value;
578 if (!result.isNewEntry) {
579 if (resultPair.first->m_type == node->m_type) {
580 resultPair.first->setIsOverriddenByDuplicate();
581 resultPair.first = node;
582 } else {
583 if (resultPair.second)
584 resultPair.second->setIsOverriddenByDuplicate();
585 resultPair.second = node;
586 }
587 }
588 }
589
590 // Iterate over the remaining properties in the list.
591 for (; p; p = p->m_next) {
592 PropertyNode* node = p->m_node;
593 dst = node->isInstanceClassProperty() ? prototype : dstOrConstructor;
594
595 // Handle regular values.
596 if (node->m_type & PropertyNode::Constant) {
597 emitPutConstantProperty(generator, dst, *node);
598 continue;
599 } else if (node->m_type & PropertyNode::Spread) {
600 generator.emitNode(dst, node->m_assign);
601 continue;
602 }
603
604 RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
605 bool needsSuperBinding = node->needsSuperBinding();
606 if (needsSuperBinding)
607 emitPutHomeObject(generator, value.get(), dst);
608
609 unsigned attributes = node->isClassProperty() ? (PropertyAttribute::Accessor | PropertyAttribute::DontEnum) : static_cast<unsigned>(PropertyAttribute::Accessor);
610
611 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
612
613 // This is a get/set property which may be overridden by a computed property or spread later.
614 if (canOverrideProperties) {
615 // Computed accessors.
616 if (node->m_type & PropertyNode::Computed) {
617 RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
618 generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
619 if (node->m_type & PropertyNode::Getter)
620 generator.emitPutGetterByVal(dst, propertyName.get(), attributes, value.get());
621 else
622 generator.emitPutSetterByVal(dst, propertyName.get(), attributes, value.get());
623 continue;
624 }
625
626 if (node->m_type & PropertyNode::Getter)
627 generator.emitPutGetterById(dst, *node->name(), attributes, value.get());
628 else
629 generator.emitPutSetterById(dst, *node->name(), attributes, value.get());
630 continue;
631 }
632
633 // This is a get/set property pair.
634 GetterSetterMap& map = node->isStaticClassProperty() ? staticMap : instanceMap;
635 GetterSetterMap::iterator it = map.find(node->name()->impl());
636 ASSERT(it != map.end());
637 GetterSetterPair& pair = it->value;
638
639 // Was this already generated as a part of its partner?
640 if (pair.second == node || node->isOverriddenByDuplicate())
641 continue;
642
643 // Generate the paired node now.
644 RefPtr<RegisterID> getterReg;
645 RefPtr<RegisterID> setterReg;
646 RegisterID* secondReg = nullptr;
647
648 if (node->m_type & PropertyNode::Getter) {
649 getterReg = value;
650 if (pair.second) {
651 ASSERT(pair.second->m_type & PropertyNode::Setter);
652 setterReg = generator.emitNode(pair.second->m_assign);
653 secondReg = setterReg.get();
654 } else {
655 setterReg = generator.newTemporary();
656 generator.emitLoad(setterReg.get(), jsUndefined());
657 }
658 } else {
659 ASSERT(node->m_type & PropertyNode::Setter);
660 setterReg = value;
661 if (pair.second) {
662 ASSERT(pair.second->m_type & PropertyNode::Getter);
663 getterReg = generator.emitNode(pair.second->m_assign);
664 secondReg = getterReg.get();
665 } else {
666 getterReg = generator.newTemporary();
667 generator.emitLoad(getterReg.get(), jsUndefined());
668 }
669 }
670
671 ASSERT(!pair.second || needsSuperBinding == pair.second->needsSuperBinding());
672 if (needsSuperBinding && pair.second)
673 emitPutHomeObject(generator, secondReg, dst);
674
675 generator.emitPutGetterSetter(dst, *node->name(), attributes, getterReg.get(), setterReg.get());
676 }
677 }
678
679 return dstOrConstructor;
680}
681
682void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
683{
684 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
685 if (node.needsSuperBinding())
686 emitPutHomeObject(generator, value.get(), newObj);
687
688 if (node.isClassProperty()) {
689 ASSERT(node.needsSuperBinding());
690 RefPtr<RegisterID> propertyNameRegister;
691 if (node.name())
692 propertyNameRegister = generator.emitLoad(nullptr, *node.name());
693 else
694 propertyNameRegister = generator.emitNode(node.m_expression);
695
696 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
697 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
698 return;
699 }
700 if (const auto* identifier = node.name()) {
701 Optional<uint32_t> optionalIndex = parseIndex(*identifier);
702 if (!optionalIndex) {
703 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
704 return;
705 }
706
707 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
708 generator.emitDirectPutByVal(newObj, index.get(), value.get());
709 return;
710 }
711 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
712 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
713 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
714}
715
716// ------------------------------ BracketAccessorNode --------------------------------
717
718static bool isNonIndexStringElement(ExpressionNode& element)
719{
720 return element.isString() && !parseIndex(static_cast<StringNode&>(element).value());
721}
722
723RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
724{
725 if (m_base->isSuperNode()) {
726 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
727 RefPtr<RegisterID> thisValue = generator.ensureThis();
728 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
729
730 if (isNonIndexStringElement(*m_subscript)) {
731 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
732 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
733 generator.emitGetById(finalDest.get(), superBase.get(), thisValue.get(), id);
734 } else {
735 RefPtr<RegisterID> subscript = generator.emitNodeForProperty(m_subscript);
736 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
737 generator.emitGetByVal(finalDest.get(), superBase.get(), thisValue.get(), subscript.get());
738 }
739
740 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
741 return finalDest.get();
742 }
743
744 RegisterID* ret;
745 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
746
747 if (isNonIndexStringElement(*m_subscript)) {
748 RefPtr<RegisterID> base = generator.emitNode(m_base);
749 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
750 ret = generator.emitGetById(finalDest.get(), base.get(), static_cast<StringNode*>(m_subscript)->value());
751 } else {
752 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
753 RegisterID* property = generator.emitNodeForProperty(m_subscript);
754 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
755 ret = generator.emitGetByVal(finalDest.get(), base.get(), property);
756 }
757
758 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
759 return ret;
760}
761
762// ------------------------------ DotAccessorNode --------------------------------
763
764RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
765{
766 bool baseIsSuper = m_base->isSuperNode();
767 RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
768 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
769 RegisterID* finalDest = generator.finalDestination(dst);
770 RegisterID* ret;
771 if (baseIsSuper) {
772 RefPtr<RegisterID> thisValue = generator.ensureThis();
773 ret = generator.emitGetById(finalDest, base.get(), thisValue.get(), m_ident);
774 } else
775 ret = generator.emitGetById(finalDest, base.get(), m_ident);
776 generator.emitProfileType(finalDest, divotStart(), divotEnd());
777 return ret;
778}
779
780// ------------------------------ ArgumentListNode -----------------------------
781
782RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
783{
784 ASSERT(m_expr);
785 return generator.emitNode(dst, m_expr);
786}
787
788// ------------------------------ NewExprNode ----------------------------------
789
790RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
791{
792 ExpectedFunction expectedFunction;
793 if (m_expr->isResolveNode())
794 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
795 else
796 expectedFunction = NoExpectedFunction;
797 RefPtr<RegisterID> func = generator.emitNode(m_expr);
798 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
799 CallArguments callArguments(generator, m_args);
800 return generator.emitConstruct(returnValue.get(), func.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
801}
802
803CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
804 : m_argumentsNode(argumentsNode)
805 , m_padding(0)
806{
807 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
808 if (argumentsNode) {
809 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
810 ++argumentCountIncludingThis;
811 }
812
813 m_argv.grow(argumentCountIncludingThis);
814 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
815 m_argv[i] = generator.newTemporary();
816 ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() - 1);
817 }
818
819 // We need to ensure that the frame size is stack-aligned
820 while ((CallFrame::headerSizeInRegisters + m_argv.size()) % stackAlignmentRegisters()) {
821 m_argv.insert(0, generator.newTemporary());
822 m_padding++;
823 }
824
825 while (stackOffset() % stackAlignmentRegisters()) {
826 m_argv.insert(0, generator.newTemporary());
827 m_padding++;
828 }
829}
830
831// ------------------------------ EvalFunctionCallNode ----------------------------------
832
833RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
834{
835 // We need try to load 'this' before call eval in constructor, because 'this' can created by 'super' in some of the arrow function
836 // var A = class A {
837 // constructor () { this.id = 'A'; }
838 // }
839 //
840 // var B = class B extend A {
841 // constructor () {
842 // var arrow = () => super();
843 // arrow();
844 // eval("this.id = 'B'");
845 // }
846 // }
847 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
848 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
849
850 Variable var = generator.variable(generator.propertyNames().eval);
851 if (RegisterID* local = var.local()) {
852 generator.emitTDZCheckIfNecessary(var, local, nullptr);
853 RefPtr<RegisterID> func = generator.move(generator.tempDestination(dst), local);
854 CallArguments callArguments(generator, m_args);
855 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
856 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
857 }
858
859 RefPtr<RegisterID> func = generator.newTemporary();
860 CallArguments callArguments(generator, m_args);
861 JSTextPosition newDivot = divotStart() + 4;
862 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
863 generator.move(
864 callArguments.thisRegister(),
865 generator.emitResolveScope(callArguments.thisRegister(), var));
866 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
867 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
868 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
869}
870
871// ------------------------------ FunctionCallValueNode ----------------------------------
872
873RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
874{
875 if (m_expr->isSuperNode()) {
876 RefPtr<RegisterID> func = emitGetSuperFunctionForConstruct(generator);
877 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
878 CallArguments callArguments(generator, m_args);
879
880 ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
881 ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
882 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), generator.newTarget(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
883
884 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
885 bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
886
887 if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction()))
888 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
889
890 Ref<Label> thisIsEmptyLabel = generator.newLabel();
891 generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get());
892 generator.emitThrowReferenceError("'super()' can't be called more than once in a constructor."_s);
893 generator.emitLabel(thisIsEmptyLabel.get());
894
895 generator.move(generator.thisRegister(), ret);
896
897 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor)
898 generator.emitPutThisToArrowFunctionContextScope();
899
900 return ret;
901 }
902 RefPtr<RegisterID> func = generator.emitNode(m_expr);
903 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
904 CallArguments callArguments(generator, m_args);
905 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
906 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
907 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
908 return ret;
909}
910
911// ------------------------------ FunctionCallResolveNode ----------------------------------
912
913RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
914{
915 if (UNLIKELY(m_ident == generator.vm()->propertyNames->builtinNames().assertPrivateName())) {
916 if (ASSERT_DISABLED)
917 return generator.move(dst, generator.emitLoad(nullptr, jsUndefined()));
918 }
919
920 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
921
922 Variable var = generator.variable(m_ident);
923 if (RegisterID* local = var.local()) {
924 generator.emitTDZCheckIfNecessary(var, local, nullptr);
925 RefPtr<RegisterID> func = generator.move(generator.tempDestination(dst), local);
926 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
927 CallArguments callArguments(generator, m_args);
928 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
929 // This passes NoExpectedFunction because we expect that if the function is in a
930 // local variable, then it's not one of our built-in constructors.
931 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
932 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
933 return ret;
934 }
935
936 RefPtr<RegisterID> func = generator.newTemporary();
937 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
938 CallArguments callArguments(generator, m_args);
939
940 JSTextPosition newDivot = divotStart() + m_ident.length();
941 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
942 generator.move(
943 callArguments.thisRegister(),
944 generator.emitResolveScope(callArguments.thisRegister(), var));
945 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
946 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
947 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
948 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
949 return ret;
950}
951
952// ------------------------------ BytecodeIntrinsicNode ----------------------------------
953
954RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
955{
956 return (this->*m_emitter)(generator, dst);
957}
958
959RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getByIdDirect(BytecodeGenerator& generator, RegisterID* dst)
960{
961 ArgumentListNode* node = m_args->m_listNode;
962 RefPtr<RegisterID> base = generator.emitNode(node);
963 node = node->m_next;
964 ASSERT(node->m_expr->isString());
965 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
966 ASSERT(!node->m_next);
967 return generator.emitDirectGetById(generator.finalDestination(dst), base.get(), ident);
968}
969
970RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getByIdDirectPrivate(BytecodeGenerator& generator, RegisterID* dst)
971{
972 ArgumentListNode* node = m_args->m_listNode;
973 RefPtr<RegisterID> base = generator.emitNode(node);
974 node = node->m_next;
975 ASSERT(node->m_expr->isString());
976 SymbolImpl* symbol = generator.vm()->propertyNames->lookUpPrivateName(static_cast<StringNode*>(node->m_expr)->value());
977 ASSERT(symbol);
978 ASSERT(!node->m_next);
979 return generator.emitDirectGetById(generator.finalDestination(dst), base.get(), generator.parserArena().identifierArena().makeIdentifier(generator.vm(), symbol));
980}
981
982RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argument(BytecodeGenerator& generator, RegisterID* dst)
983{
984 ArgumentListNode* node = m_args->m_listNode;
985 ASSERT(node->m_expr->isNumber());
986 double value = static_cast<NumberNode*>(node->m_expr)->value();
987 int32_t index = static_cast<int32_t>(value);
988 ASSERT(value == index);
989 ASSERT(index >= 0);
990 ASSERT(!node->m_next);
991
992 // The body functions of generator and async have different mechanism for arguments.
993 ASSERT(generator.parseMode() != SourceParseMode::GeneratorBodyMode);
994 ASSERT(!isAsyncFunctionBodyParseMode(generator.parseMode()));
995
996 return generator.emitGetArgument(generator.finalDestination(dst), index);
997}
998
999RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator& generator, RegisterID* dst)
1000{
1001 ASSERT(!m_args->m_listNode);
1002
1003 return generator.emitArgumentCount(generator.finalDestination(dst));
1004}
1005
1006RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByIdDirect(BytecodeGenerator& generator, RegisterID* dst)
1007{
1008 ArgumentListNode* node = m_args->m_listNode;
1009 RefPtr<RegisterID> base = generator.emitNode(node);
1010 node = node->m_next;
1011 ASSERT(node->m_expr->isString());
1012 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1013 node = node->m_next;
1014 RefPtr<RegisterID> value = generator.emitNode(node);
1015
1016 ASSERT(!node->m_next);
1017
1018 return generator.move(dst, generator.emitDirectPutById(base.get(), ident, value.get(), PropertyNode::KnownDirect));
1019}
1020
1021RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByIdDirectPrivate(BytecodeGenerator& generator, RegisterID* dst)
1022{
1023 ArgumentListNode* node = m_args->m_listNode;
1024 RefPtr<RegisterID> base = generator.emitNode(node);
1025 node = node->m_next;
1026 ASSERT(node->m_expr->isString());
1027 SymbolImpl* symbol = generator.vm()->propertyNames->lookUpPrivateName(static_cast<StringNode*>(node->m_expr)->value());
1028 ASSERT(symbol);
1029 node = node->m_next;
1030 RefPtr<RegisterID> value = generator.emitNode(node);
1031
1032 ASSERT(!node->m_next);
1033
1034 return generator.move(dst, generator.emitDirectPutById(base.get(), generator.parserArena().identifierArena().makeIdentifier(generator.vm(), symbol), value.get(), PropertyNode::KnownDirect));
1035}
1036
1037RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
1038{
1039 ArgumentListNode* node = m_args->m_listNode;
1040 RefPtr<RegisterID> base = generator.emitNode(node);
1041 node = node->m_next;
1042 RefPtr<RegisterID> index = generator.emitNodeForProperty(node);
1043 node = node->m_next;
1044 RefPtr<RegisterID> value = generator.emitNode(node);
1045
1046 ASSERT(!node->m_next);
1047
1048 return generator.move(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
1049}
1050
1051RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator& generator, RegisterID* dst)
1052{
1053 ArgumentListNode* node = m_args->m_listNode;
1054 RefPtr<RegisterID> function = generator.emitNode(node);
1055 node = node->m_next;
1056 RefPtr<RegisterID> thisRegister = generator.emitNode(node);
1057 ASSERT(!node->m_next);
1058
1059 RefPtr<RegisterID> finalDst = generator.finalDestination(dst);
1060 return generator.emitCallForwardArgumentsInTailPosition(finalDst.get(), function.get(), thisRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd(), DebuggableCall::No);
1061}
1062
1063RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwTypeError(BytecodeGenerator& generator, RegisterID* dst)
1064{
1065 ArgumentListNode* node = m_args->m_listNode;
1066 ASSERT(!node->m_next);
1067 if (node->m_expr->isString()) {
1068 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1069 generator.emitThrowTypeError(ident);
1070 } else {
1071 RefPtr<RegisterID> message = generator.emitNode(node);
1072 generator.emitThrowStaticError(ErrorType::TypeError, message.get());
1073 }
1074 return dst;
1075}
1076
1077RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwRangeError(BytecodeGenerator& generator, RegisterID* dst)
1078{
1079 ArgumentListNode* node = m_args->m_listNode;
1080 ASSERT(!node->m_next);
1081 if (node->m_expr->isString()) {
1082 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1083 generator.emitThrowRangeError(ident);
1084 } else {
1085 RefPtr<RegisterID> message = generator.emitNode(node);
1086 generator.emitThrowStaticError(ErrorType::RangeError, message.get());
1087 }
1088
1089 return dst;
1090}
1091
1092RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwOutOfMemoryError(BytecodeGenerator& generator, RegisterID* dst)
1093{
1094 ASSERT(!m_args->m_listNode);
1095
1096 generator.emitThrowOutOfMemoryError();
1097 return dst;
1098}
1099
1100RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
1101{
1102 ArgumentListNode* node = m_args->m_listNode;
1103 RefPtr<RegisterID> base = generator.emitNode(node);
1104 node = node->m_next;
1105
1106 // Since this is a builtin we expect the creator to use a string literal as the second argument.
1107 ASSERT(node->m_expr->isString());
1108 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1109 ASSERT(!node->m_next);
1110
1111 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
1112 return generator.emitTryGetById(finalDest.get(), base.get(), ident);
1113}
1114
1115RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toNumber(BytecodeGenerator& generator, RegisterID* dst)
1116{
1117 ArgumentListNode* node = m_args->m_listNode;
1118 RefPtr<RegisterID> src = generator.emitNode(node);
1119 ASSERT(!node->m_next);
1120
1121 return generator.move(dst, generator.emitToNumber(generator.tempDestination(dst), src.get()));
1122}
1123
1124RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
1125{
1126 ArgumentListNode* node = m_args->m_listNode;
1127 RefPtr<RegisterID> src = generator.emitNode(node);
1128 ASSERT(!node->m_next);
1129
1130 return generator.move(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
1131}
1132
1133RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toObject(BytecodeGenerator& generator, RegisterID* dst)
1134{
1135 ArgumentListNode* node = m_args->m_listNode;
1136 RefPtr<RegisterID> src = generator.emitNode(node);
1137 node = node->m_next;
1138
1139 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1140 if (node) {
1141 ASSERT(node->m_expr->isString());
1142 const Identifier& message = static_cast<StringNode*>(node->m_expr)->value();
1143 ASSERT(!node->m_next);
1144 return generator.move(dst, generator.emitToObject(temp.get(), src.get(), message));
1145 }
1146 return generator.move(dst, generator.emitToObject(temp.get(), src.get(), generator.vm()->propertyNames->emptyIdentifier));
1147}
1148
1149RegisterID* BytecodeIntrinsicNode::emit_intrinsic_idWithProfile(BytecodeGenerator& generator, RegisterID* dst)
1150{
1151 ArgumentListNode* node = m_args->m_listNode;
1152 RefPtr<RegisterID> idValue = generator.newTemporary();
1153 generator.emitNode(idValue.get(), node);
1154 SpeculatedType speculation = SpecNone;
1155 while (node->m_next) {
1156 node = node->m_next;
1157 ASSERT(node->m_expr->isString());
1158 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1159 speculation |= speculationFromString(ident.utf8().data());
1160 }
1161
1162 return generator.move(dst, generator.emitIdWithProfile(idValue.get(), speculation));
1163}
1164
1165RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isJSArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1166{
1167 ArgumentListNode* node = m_args->m_listNode;
1168 RefPtr<RegisterID> src = generator.emitNode(node);
1169 ASSERT(!node->m_next);
1170
1171 return generator.move(dst, generator.emitIsJSArray(generator.tempDestination(dst), src.get()));
1172}
1173
1174RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1175{
1176 ArgumentListNode* node = m_args->m_listNode;
1177 RefPtr<RegisterID> src = generator.emitNode(node);
1178 ASSERT(!node->m_next);
1179
1180 return generator.move(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
1181}
1182
1183RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1184{
1185 ArgumentListNode* node = m_args->m_listNode;
1186 RefPtr<RegisterID> src = generator.emitNode(node);
1187 ASSERT(!node->m_next);
1188
1189 return generator.move(dst, generator.emitIsRegExpObject(generator.tempDestination(dst), src.get()));
1190}
1191
1192RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
1193{
1194 ArgumentListNode* node = m_args->m_listNode;
1195 RefPtr<RegisterID> src = generator.emitNode(node);
1196 ASSERT(!node->m_next);
1197
1198 return generator.move(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
1199}
1200
1201RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1202{
1203 ArgumentListNode* node = m_args->m_listNode;
1204 RefPtr<RegisterID> src = generator.emitNode(node);
1205 ASSERT(!node->m_next);
1206
1207 return generator.move(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
1208}
1209
1210RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isMap(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1211{
1212 ArgumentListNode* node = m_args->m_listNode;
1213 RefPtr<RegisterID> src = generator.emitNode(node);
1214 ASSERT(!node->m_next);
1215
1216 return generator.move(dst, generator.emitIsMap(generator.tempDestination(dst), src.get()));
1217}
1218
1219RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isSet(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1220{
1221 ArgumentListNode* node = m_args->m_listNode;
1222 RefPtr<RegisterID> src = generator.emitNode(node);
1223 ASSERT(!node->m_next);
1224
1225 return generator.move(dst, generator.emitIsSet(generator.tempDestination(dst), src.get()));
1226}
1227
1228RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isUndefinedOrNull(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1229{
1230 ArgumentListNode* node = m_args->m_listNode;
1231 RefPtr<RegisterID> src = generator.emitNode(node);
1232 ASSERT(!node->m_next);
1233
1234 return generator.move(dst, generator.emitIsUndefinedOrNull(generator.tempDestination(dst), src.get()));
1235}
1236
1237RegisterID* BytecodeIntrinsicNode::emit_intrinsic_newArrayWithSize(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1238{
1239 ArgumentListNode* node = m_args->m_listNode;
1240 RefPtr<RegisterID> size = generator.emitNode(node);
1241 ASSERT(!node->m_next);
1242
1243 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst);
1244 generator.emitNewArrayWithSize(finalDestination.get(), size.get());
1245 return finalDestination.get();
1246}
1247
1248RegisterID* BytecodeIntrinsicNode::emit_intrinsic_defineEnumerableWritableConfigurableDataProperty(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1249{
1250 ArgumentListNode* node = m_args->m_listNode;
1251 RefPtr<RegisterID> newObj = generator.emitNode(node);
1252 node = node->m_next;
1253 RefPtr<RegisterID> propertyNameRegister = generator.emitNode(node);
1254 node = node->m_next;
1255 RefPtr<RegisterID> value = generator.emitNode(node);
1256 ASSERT(!node->m_next);
1257
1258 generator.emitCallDefineProperty(newObj.get(), propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable | BytecodeGenerator::PropertyEnumerable, m_position);
1259 return dst;
1260}
1261
1262#define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \
1263 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_##name(BytecodeGenerator& generator, RegisterID* dst) \
1264 { \
1265 ASSERT(!m_args); \
1266 ASSERT(type() == Type::Constant); \
1267 if (dst == generator.ignoredResult()) \
1268 return nullptr; \
1269 return generator.emitLoad(dst, generator.vm()->bytecodeIntrinsicRegistry().name##Value(generator)); \
1270 }
1271 JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
1272#undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
1273
1274// ------------------------------ FunctionCallBracketNode ----------------------------------
1275
1276RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1277{
1278 bool baseIsSuper = m_base->isSuperNode();
1279 bool subscriptIsNonIndexString = isNonIndexStringElement(*m_subscript);
1280
1281 RefPtr<RegisterID> base;
1282 if (baseIsSuper)
1283 base = emitSuperBaseForCallee(generator);
1284 else {
1285 if (subscriptIsNonIndexString)
1286 base = generator.emitNode(m_base);
1287 else
1288 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
1289 }
1290
1291 RefPtr<RegisterID> function;
1292 RefPtr<RegisterID> thisRegister;
1293 if (baseIsSuper) {
1294 // Note that we only need to do this once because we either have a non-TDZ this or we throw. Once we have a non-TDZ this, we can't change its value back to TDZ.
1295 thisRegister = generator.ensureThis();
1296 }
1297 if (subscriptIsNonIndexString) {
1298 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1299 if (baseIsSuper)
1300 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisRegister.get(), static_cast<StringNode*>(m_subscript)->value());
1301 else
1302 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
1303 } else {
1304 RefPtr<RegisterID> property = generator.emitNodeForProperty(m_subscript);
1305 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1306 if (baseIsSuper)
1307 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisRegister.get(), property.get());
1308 else
1309 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1310 }
1311
1312 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
1313 CallArguments callArguments(generator, m_args);
1314 if (baseIsSuper) {
1315 generator.emitTDZCheck(generator.thisRegister());
1316 generator.move(callArguments.thisRegister(), thisRegister.get());
1317 } else
1318 generator.move(callArguments.thisRegister(), base.get());
1319 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1320 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
1321 return ret;
1322}
1323
1324// ------------------------------ FunctionCallDotNode ----------------------------------
1325
1326RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1327{
1328 RefPtr<RegisterID> function = generator.tempDestination(dst);
1329 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
1330 CallArguments callArguments(generator, m_args);
1331 bool baseIsSuper = m_base->isSuperNode();
1332 if (baseIsSuper)
1333 generator.move(callArguments.thisRegister(), generator.ensureThis());
1334 else
1335 generator.emitNode(callArguments.thisRegister(), m_base);
1336 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1337 if (baseIsSuper) {
1338 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
1339 generator.emitGetById(function.get(), superBase.get(), callArguments.thisRegister(), m_ident);
1340 } else
1341 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
1342 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1343 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
1344 return ret;
1345}
1346
1347static constexpr size_t maxDistanceToInnermostCallOrApply = 2;
1348
1349RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1350{
1351 RefPtr<RegisterID> base = generator.emitNode(m_base);
1352 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1353 RefPtr<RegisterID> function;
1354 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
1355
1356 auto makeFunction = [&] {
1357 if (m_base->isSuperNode()) {
1358 RefPtr<RegisterID> thisValue = generator.ensureThis();
1359 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().callPublicName());
1360 } else
1361 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
1362 };
1363
1364 bool emitCallCheck = !generator.isBuiltinFunction();
1365 if (m_distanceToInnermostCallOrApply > maxDistanceToInnermostCallOrApply && emitCallCheck) {
1366 makeFunction();
1367 CallArguments callArguments(generator, m_args);
1368 generator.move(callArguments.thisRegister(), base.get());
1369 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1370 generator.move(dst, returnValue.get());
1371 return returnValue.get();
1372 }
1373
1374 Ref<Label> realCall = generator.newLabel();
1375 Ref<Label> end = generator.newLabel();
1376
1377 if (emitCallCheck) {
1378 makeFunction();
1379 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
1380 }
1381 {
1382 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
1383 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
1384 ExpressionNode* subject = spread->expression();
1385 RefPtr<RegisterID> argumentsRegister;
1386 argumentsRegister = generator.emitNode(subject);
1387 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
1388 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
1389 generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1390 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
1391 ArgumentListNode* oldList = m_args->m_listNode;
1392 m_args->m_listNode = m_args->m_listNode->m_next;
1393
1394 RefPtr<RegisterID> realFunction = generator.move(generator.tempDestination(dst), base.get());
1395 CallArguments callArguments(generator, m_args);
1396 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
1397 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1398 m_args->m_listNode = oldList;
1399 } else {
1400 RefPtr<RegisterID> realFunction = generator.move(generator.tempDestination(dst), base.get());
1401 CallArguments callArguments(generator, m_args);
1402 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
1403 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1404 }
1405 }
1406 if (emitCallCheck) {
1407 generator.emitJump(end.get());
1408 generator.emitLabel(realCall.get());
1409 {
1410 CallArguments callArguments(generator, m_args);
1411 generator.move(callArguments.thisRegister(), base.get());
1412 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1413 }
1414 generator.emitLabel(end.get());
1415 }
1416 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
1417 return returnValue.get();
1418}
1419
1420static bool areTrivialApplyArguments(ArgumentsNode* args)
1421{
1422 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
1423 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
1424}
1425
1426RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1427{
1428 // A few simple cases can be trivially handled as ordinary function calls.
1429 // function.apply(), function.apply(arg) -> identical to function.call
1430 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
1431 bool mayBeCall = areTrivialApplyArguments(m_args);
1432
1433 RefPtr<RegisterID> function;
1434 RefPtr<RegisterID> base = generator.emitNode(m_base);
1435 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
1436 auto makeFunction = [&] {
1437 if (m_base->isSuperNode()) {
1438 RefPtr<RegisterID> thisValue = generator.ensureThis();
1439 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().applyPublicName());
1440 } else
1441 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
1442 };
1443
1444 bool emitCallCheck = !generator.isBuiltinFunction();
1445 if (m_distanceToInnermostCallOrApply > maxDistanceToInnermostCallOrApply && emitCallCheck) {
1446 makeFunction();
1447 CallArguments callArguments(generator, m_args);
1448 generator.move(callArguments.thisRegister(), base.get());
1449 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1450 generator.move(dst, returnValue.get());
1451 return returnValue.get();
1452 }
1453
1454 Ref<Label> realCall = generator.newLabel();
1455 Ref<Label> end = generator.newLabel();
1456 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1457 if (emitCallCheck) {
1458 makeFunction();
1459 ASSERT(!m_base->isResolveNode() || static_cast<ResolveNode*>(m_base)->identifier() != "Reflect");
1460 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
1461 }
1462 if (mayBeCall) {
1463 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
1464 ArgumentListNode* oldList = m_args->m_listNode;
1465 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
1466 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
1467 RefPtr<RegisterID> realFunction = generator.move(generator.newTemporary(), base.get());
1468 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
1469 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1470 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1471
1472 auto extractor = scopedLambda<void(BytecodeGenerator&, RegisterID*)>([&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
1473 {
1474 Ref<Label> haveThis = generator.newLabel();
1475 Ref<Label> end = generator.newLabel();
1476 RefPtr<RegisterID> compareResult = generator.newTemporary();
1477 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp<OpEq>(compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1478 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
1479 generator.move(thisRegister.get(), value);
1480 generator.emitLoad(index.get(), jsNumber(1));
1481 generator.emitJump(end.get());
1482 generator.emitLabel(haveThis.get());
1483 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp<OpEq>(compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1484 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
1485 generator.move(argumentsRegister.get(), value);
1486 generator.emitLoad(index.get(), jsNumber(2));
1487 generator.emitLabel(end.get());
1488 });
1489 generator.emitEnumeration(this, spread->expression(), extractor);
1490 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1491 } else if (m_args->m_listNode->m_next) {
1492 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
1493 ASSERT(!m_args->m_listNode->m_next->m_next);
1494 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.parserArena(), 0, 0);
1495 RefPtr<RegisterID> realFunction = generator.move(generator.tempDestination(dst), base.get());
1496 CallArguments callArguments(generator, m_args);
1497 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
1498 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1499 } else {
1500 m_args->m_listNode = m_args->m_listNode->m_next;
1501 RefPtr<RegisterID> realFunction = generator.move(generator.tempDestination(dst), base.get());
1502 CallArguments callArguments(generator, m_args);
1503 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
1504 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1505 }
1506 m_args->m_listNode = oldList;
1507 } else {
1508 RefPtr<RegisterID> realFunction = generator.move(generator.tempDestination(dst), base.get());
1509 CallArguments callArguments(generator, m_args);
1510 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
1511 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1512 }
1513 } else {
1514 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
1515 RefPtr<RegisterID> realFunction = generator.move(generator.tempDestination(dst), base.get());
1516 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
1517 RefPtr<RegisterID> argsRegister;
1518 ArgumentListNode* args = m_args->m_listNode->m_next;
1519 argsRegister = generator.emitNode(args->m_expr);
1520
1521 // Function.prototype.apply ignores extra arguments, but we still
1522 // need to evaluate them for side effects.
1523 while ((args = args->m_next))
1524 generator.emitNode(args->m_expr);
1525
1526 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1527 }
1528 if (emitCallCheck) {
1529 generator.emitJump(end.get());
1530 generator.emitLabel(realCall.get());
1531 CallArguments callArguments(generator, m_args);
1532 generator.move(callArguments.thisRegister(), base.get());
1533 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1534 generator.emitLabel(end.get());
1535 }
1536 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
1537 return returnValue.get();
1538}
1539
1540// ------------------------------ PostfixNode ----------------------------------
1541
1542static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
1543{
1544 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
1545}
1546
1547static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1548{
1549 if (dst == srcDst)
1550 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1551 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1552 emitIncOrDec(generator, srcDst, oper);
1553 return generator.move(dst, tmp.get());
1554}
1555
1556RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
1557{
1558 if (dst == generator.ignoredResult())
1559 return PrefixNode::emitResolve(generator, dst);
1560
1561 ASSERT(m_expr->isResolveNode());
1562 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1563 const Identifier& ident = resolve->identifier();
1564
1565 Variable var = generator.variable(ident);
1566 if (RegisterID* local = var.local()) {
1567 generator.emitTDZCheckIfNecessary(var, local, nullptr);
1568 RefPtr<RegisterID> localReg = local;
1569 if (var.isReadOnly()) {
1570 generator.emitReadOnlyExceptionIfNeeded(var);
1571 localReg = generator.move(generator.tempDestination(dst), local);
1572 }
1573 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1574 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1575 return oldValue.get();
1576 }
1577
1578 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1579 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1580 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
1581 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
1582 if (var.isReadOnly()) {
1583 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1584 if (threwException)
1585 return value.get();
1586 }
1587 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
1588 if (!var.isReadOnly()) {
1589 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
1590 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1591 }
1592
1593 return oldValue.get();
1594}
1595
1596RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
1597{
1598 if (dst == generator.ignoredResult())
1599 return PrefixNode::emitBracket(generator, dst);
1600
1601 ASSERT(m_expr->isBracketAccessorNode());
1602 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1603 ExpressionNode* baseNode = bracketAccessor->base();
1604 ExpressionNode* subscript = bracketAccessor->subscript();
1605
1606 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
1607 RefPtr<RegisterID> property = generator.emitNodeForProperty(subscript);
1608
1609 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
1610 RefPtr<RegisterID> value;
1611 RefPtr<RegisterID> thisValue;
1612 if (baseNode->isSuperNode()) {
1613 thisValue = generator.ensureThis();
1614 value = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
1615 } else
1616 value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
1617 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
1618 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1619 if (baseNode->isSuperNode())
1620 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value.get());
1621 else
1622 generator.emitPutByVal(base.get(), property.get(), value.get());
1623 generator.emitProfileType(value.get(), divotStart(), divotEnd());
1624 return generator.move(dst, oldValue);
1625}
1626
1627RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
1628{
1629 if (dst == generator.ignoredResult())
1630 return PrefixNode::emitDot(generator, dst);
1631
1632 ASSERT(m_expr->isDotAccessorNode());
1633 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1634 ExpressionNode* baseNode = dotAccessor->base();
1635 bool baseIsSuper = baseNode->isSuperNode();
1636 const Identifier& ident = dotAccessor->identifier();
1637
1638 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1639
1640 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
1641 RefPtr<RegisterID> value;
1642 RefPtr<RegisterID> thisValue;
1643 if (baseIsSuper) {
1644 thisValue = generator.ensureThis();
1645 value = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), ident);
1646 } else
1647 value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
1648 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
1649 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1650 if (baseIsSuper)
1651 generator.emitPutById(base.get(), thisValue.get(), ident, value.get());
1652 else
1653 generator.emitPutById(base.get(), ident, value.get());
1654 generator.emitProfileType(value.get(), divotStart(), divotEnd());
1655 return generator.move(dst, oldValue);
1656}
1657
1658RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1659{
1660 if (m_expr->isResolveNode())
1661 return emitResolve(generator, dst);
1662
1663 if (m_expr->isBracketAccessorNode())
1664 return emitBracket(generator, dst);
1665
1666 if (m_expr->isDotAccessorNode())
1667 return emitDot(generator, dst);
1668
1669 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
1670 ? "Postfix ++ operator applied to value that is not a reference."_s
1671 : "Postfix -- operator applied to value that is not a reference."_s);
1672}
1673
1674// ------------------------------ DeleteResolveNode -----------------------------------
1675
1676RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1677{
1678 Variable var = generator.variable(m_ident);
1679 if (var.local()) {
1680 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
1681 return generator.emitLoad(generator.finalDestination(dst), false);
1682 }
1683
1684 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1685 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
1686 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
1687 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
1688}
1689
1690// ------------------------------ DeleteBracketNode -----------------------------------
1691
1692RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1693{
1694 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
1695 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
1696
1697 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1698 if (m_base->isSuperNode())
1699 return emitThrowReferenceError(generator, "Cannot delete a super property");
1700 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
1701}
1702
1703// ------------------------------ DeleteDotNode -----------------------------------
1704
1705RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1706{
1707 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
1708
1709 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1710 if (m_base->isSuperNode())
1711 return emitThrowReferenceError(generator, "Cannot delete a super property");
1712 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
1713}
1714
1715// ------------------------------ DeleteValueNode -----------------------------------
1716
1717RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1718{
1719 generator.emitNode(generator.ignoredResult(), m_expr);
1720
1721 // delete on a non-location expression ignores the value and returns true
1722 return generator.emitLoad(generator.finalDestination(dst), true);
1723}
1724
1725// ------------------------------ VoidNode -------------------------------------
1726
1727RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1728{
1729 if (dst == generator.ignoredResult()) {
1730 generator.emitNode(generator.ignoredResult(), m_expr);
1731 return 0;
1732 }
1733 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1734 return generator.emitLoad(dst, jsUndefined());
1735}
1736
1737// ------------------------------ TypeOfResolveNode -----------------------------------
1738
1739RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1740{
1741 Variable var = generator.variable(m_ident);
1742 if (RegisterID* local = var.local()) {
1743 generator.emitTDZCheckIfNecessary(var, local, nullptr);
1744 if (dst == generator.ignoredResult())
1745 return 0;
1746 return generator.emitTypeOf(generator.finalDestination(dst), local);
1747 }
1748
1749 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1750 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
1751 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
1752 if (dst == generator.ignoredResult())
1753 return 0;
1754 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
1755}
1756
1757// ------------------------------ TypeOfValueNode -----------------------------------
1758
1759RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1760{
1761 if (dst == generator.ignoredResult()) {
1762 generator.emitNode(generator.ignoredResult(), m_expr);
1763 return 0;
1764 }
1765 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1766 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1767}
1768
1769// ------------------------------ PrefixNode ----------------------------------
1770
1771RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
1772{
1773 ASSERT(m_expr->isResolveNode());
1774 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1775 const Identifier& ident = resolve->identifier();
1776
1777 Variable var = generator.variable(ident);
1778 if (RegisterID* local = var.local()) {
1779 generator.emitTDZCheckIfNecessary(var, local, nullptr);
1780 RefPtr<RegisterID> localReg = local;
1781 if (var.isReadOnly()) {
1782 generator.emitReadOnlyExceptionIfNeeded(var);
1783 localReg = generator.move(generator.tempDestination(dst), localReg.get());
1784 } else if (generator.vm()->typeProfiler()) {
1785 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1786 generator.move(tempDst.get(), localReg.get());
1787 emitIncOrDec(generator, tempDst.get(), m_operator);
1788 generator.move(localReg.get(), tempDst.get());
1789 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1790 return generator.move(dst, tempDst.get());
1791 }
1792 emitIncOrDec(generator, localReg.get(), m_operator);
1793 return generator.move(dst, localReg.get());
1794 }
1795
1796 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1797 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1798 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
1799 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
1800 if (var.isReadOnly()) {
1801 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1802 if (threwException)
1803 return value.get();
1804 }
1805
1806 emitIncOrDec(generator, value.get(), m_operator);
1807 if (!var.isReadOnly()) {
1808 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
1809 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1810 }
1811 return generator.move(dst, value.get());
1812}
1813
1814RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
1815{
1816 ASSERT(m_expr->isBracketAccessorNode());
1817 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1818 ExpressionNode* baseNode = bracketAccessor->base();
1819 ExpressionNode* subscript = bracketAccessor->subscript();
1820
1821 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
1822 RefPtr<RegisterID> property = generator.emitNodeForProperty(subscript);
1823 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1824
1825 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
1826 RegisterID* value;
1827 RefPtr<RegisterID> thisValue;
1828 if (baseNode->isSuperNode()) {
1829 thisValue = generator.ensureThis();
1830 value = generator.emitGetByVal(propDst.get(), base.get(), thisValue.get(), property.get());
1831 } else
1832 value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
1833 emitIncOrDec(generator, value, m_operator);
1834 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1835 if (baseNode->isSuperNode())
1836 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
1837 else
1838 generator.emitPutByVal(base.get(), property.get(), value);
1839 generator.emitProfileType(value, divotStart(), divotEnd());
1840 return generator.move(dst, propDst.get());
1841}
1842
1843RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
1844{
1845 ASSERT(m_expr->isDotAccessorNode());
1846 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1847 ExpressionNode* baseNode = dotAccessor->base();
1848 const Identifier& ident = dotAccessor->identifier();
1849
1850 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1851 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1852
1853 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
1854 RegisterID* value;
1855 RefPtr<RegisterID> thisValue;
1856 if (baseNode->isSuperNode()) {
1857 thisValue = generator.ensureThis();
1858 value = generator.emitGetById(propDst.get(), base.get(), thisValue.get(), ident);
1859 } else
1860 value = generator.emitGetById(propDst.get(), base.get(), ident);
1861 emitIncOrDec(generator, value, m_operator);
1862 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1863 if (baseNode->isSuperNode())
1864 generator.emitPutById(base.get(), thisValue.get(), ident, value);
1865 else
1866 generator.emitPutById(base.get(), ident, value);
1867 generator.emitProfileType(value, divotStart(), divotEnd());
1868 return generator.move(dst, propDst.get());
1869}
1870
1871RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1872{
1873 if (m_expr->isResolveNode())
1874 return emitResolve(generator, dst);
1875
1876 if (m_expr->isBracketAccessorNode())
1877 return emitBracket(generator, dst);
1878
1879 if (m_expr->isDotAccessorNode())
1880 return emitDot(generator, dst);
1881
1882 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
1883 ? "Prefix ++ operator applied to value that is not a reference."_s
1884 : "Prefix -- operator applied to value that is not a reference."_s);
1885}
1886
1887// ------------------------------ Unary Operation Nodes -----------------------------------
1888
1889RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1890{
1891 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1892 generator.emitExpressionInfo(position(), position(), position());
1893 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor()));
1894}
1895
1896// ------------------------------ UnaryPlusNode -----------------------------------
1897
1898RegisterID* UnaryPlusNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1899{
1900 ASSERT(opcodeID() == op_to_number);
1901 RefPtr<RegisterID> src = generator.emitNode(expr());
1902 generator.emitExpressionInfo(position(), position(), position());
1903 return generator.emitToNumber(generator.finalDestination(dst), src.get());
1904}
1905
1906// ------------------------------ LogicalNotNode -----------------------------------
1907
1908void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
1909{
1910 if (UNLIKELY(needsDebugHook()))
1911 generator.emitDebugHook(this);
1912
1913 // Reverse the true and false targets.
1914 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
1915}
1916
1917
1918// ------------------------------ Binary Operation Nodes -----------------------------------
1919
1920// BinaryOpNode::emitStrcat:
1921//
1922// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1923// more values, where we can determine a set of separate op_add operations would be operating on
1924// string values.
1925//
1926// This function expects to be operating on a graph of AST nodes looking something like this:
1927//
1928// (a)... (b)
1929// \ /
1930// (+) (c)
1931// \ /
1932// [d] ((+))
1933// \ /
1934// [+=]
1935//
1936// The assignment operation is optional, if it exists the register holding the value on the
1937// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1938//
1939// The method should be called on the node at the root of the tree of regular binary add
1940// operations (marked in the diagram with a double set of parentheses). This node must
1941// be performing a string concatenation (determined by statically detecting that at least
1942// one child must be a string).
1943//
1944// Since the minimum number of values being concatenated together is expected to be 3, if
1945// a lhs to a concatenating assignment is not provided then the root add should have at
1946// least one left child that is also an add that can be determined to be operating on strings.
1947//
1948RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1949{
1950 ASSERT(isAdd());
1951 ASSERT(resultDescriptor().definitelyIsString());
1952
1953 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1954 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1955 // added first, and the leftmost child is never added, so the vector produced for the
1956 // example above will be [ c, b ].
1957 Vector<ExpressionNode*, 16> reverseExpressionList;
1958 reverseExpressionList.append(m_expr2);
1959
1960 // Examine the left child of the add. So long as this is a string add, add its right-child
1961 // to the list, and keep processing along the left fork.
1962 ExpressionNode* leftMostAddChild = m_expr1;
1963 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1964 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1965 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1966 }
1967
1968 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1969
1970 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1971 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1972 // op_strcat node handle its conversion if required).
1973 if (lhs)
1974 temporaryRegisters.append(generator.newTemporary());
1975
1976 // Emit code for the leftmost node ((a) in the example).
1977 temporaryRegisters.append(generator.newTemporary());
1978 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1979 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1980
1981 // Note on ordering of conversions:
1982 //
1983 // We maintain the same ordering of conversions as we would see if the concatenations
1984 // was performed as a sequence of adds (otherwise this optimization could change
1985 // behaviour should an object have been provided a valueOf or toString method).
1986 //
1987 // Considering the above example, the sequnce of execution is:
1988 // * evaluate operand (a)
1989 // * evaluate operand (b)
1990 // * convert (a) to primitive <- (this would be triggered by the first add)
1991 // * convert (b) to primitive <- (ditto)
1992 // * evaluate operand (c)
1993 // * convert (c) to primitive <- (this would be triggered by the second add)
1994 // And optionally, if there is an assignment:
1995 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1996 //
1997 // As such we do not plant an op to convert the leftmost child now. Instead, use
1998 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1999 // once the second node has been generated. However, if the leftmost child is an
2000 // immediate we can trivially determine that no conversion will be required.
2001 // If this is the case
2002 if (leftMostAddChild->isString())
2003 leftMostAddChildTempRegister = 0;
2004
2005 while (reverseExpressionList.size()) {
2006 ExpressionNode* node = reverseExpressionList.last();
2007 reverseExpressionList.removeLast();
2008
2009 // Emit the code for the current node.
2010 temporaryRegisters.append(generator.newTemporary());
2011 generator.emitNode(temporaryRegisters.last().get(), node);
2012
2013 // On the first iteration of this loop, when we first reach this point we have just
2014 // generated the second node, which means it is time to convert the leftmost operand.
2015 if (leftMostAddChildTempRegister) {
2016 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
2017 leftMostAddChildTempRegister = 0; // Only do this once.
2018 }
2019 // Plant a conversion for this node, if necessary.
2020 if (!node->isString())
2021 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
2022 }
2023 ASSERT(temporaryRegisters.size() >= 3);
2024
2025 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2026 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2027 if (emitExpressionInfoForMe)
2028 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
2029 // If there is an assignment convert the lhs now. This will also copy lhs to
2030 // the temporary register we allocated for it.
2031 if (lhs)
2032 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
2033
2034 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
2035}
2036
2037void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
2038{
2039 TriState branchCondition;
2040 ExpressionNode* branchExpression;
2041 tryFoldToBranch(generator, branchCondition, branchExpression);
2042
2043 if (UNLIKELY(needsDebugHook())) {
2044 if (branchCondition != MixedTriState)
2045 generator.emitDebugHook(this);
2046 }
2047
2048 if (branchCondition == MixedTriState)
2049 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
2050 else if (branchCondition == TrueTriState)
2051 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
2052 else
2053 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
2054}
2055
2056static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
2057{
2058 ResultType expressionType = branchExpression->resultDescriptor();
2059
2060 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
2061 return true;
2062 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
2063 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
2064 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
2065 return true;
2066
2067 return false;
2068}
2069
2070void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
2071{
2072 branchCondition = MixedTriState;
2073 branchExpression = 0;
2074
2075 ConstantNode* constant = 0;
2076 if (m_expr1->isConstant()) {
2077 constant = static_cast<ConstantNode*>(m_expr1);
2078 branchExpression = m_expr2;
2079 } else if (m_expr2->isConstant()) {
2080 constant = static_cast<ConstantNode*>(m_expr2);
2081 branchExpression = m_expr1;
2082 }
2083
2084 if (!constant)
2085 return;
2086 ASSERT(branchExpression);
2087
2088 OpcodeID opcodeID = this->opcodeID();
2089 JSValue value = constant->jsValue(generator);
2090 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
2091 if (!canFoldToBranch)
2092 return;
2093
2094 if (opcodeID == op_eq || opcodeID == op_stricteq)
2095 branchCondition = triState(value.pureToBoolean());
2096 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
2097 branchCondition = triState(!value.pureToBoolean());
2098}
2099
2100RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2101{
2102 OpcodeID opcodeID = this->opcodeID();
2103
2104 if (opcodeID == op_less || opcodeID == op_lesseq || opcodeID == op_greater || opcodeID == op_greatereq) {
2105 auto isUInt32 = [&] (ExpressionNode* node) -> Optional<UInt32Result> {
2106 if (node->isBinaryOpNode() && static_cast<BinaryOpNode*>(node)->opcodeID() == op_urshift)
2107 return UInt32Result::UInt32;
2108 if (node->isNumber() && static_cast<NumberNode*>(node)->isIntegerNode()) {
2109 auto value = jsNumber(static_cast<NumberNode*>(node)->value());
2110 if (value.isInt32() && value.asInt32() >= 0)
2111 return UInt32Result::Constant;
2112 }
2113 return WTF::nullopt;
2114 };
2115 auto leftResult = isUInt32(m_expr1);
2116 auto rightResult = isUInt32(m_expr2);
2117 if ((leftResult && rightResult) && (leftResult.value() == UInt32Result::UInt32 || rightResult.value() == UInt32Result::UInt32)) {
2118 auto* left = m_expr1;
2119 auto* right = m_expr2;
2120 if (left->isBinaryOpNode()) {
2121 ASSERT(static_cast<BinaryOpNode*>(left)->opcodeID() == op_urshift);
2122 static_cast<BinaryOpNode*>(left)->m_shouldToUnsignedResult = false;
2123 }
2124 if (right->isBinaryOpNode()) {
2125 ASSERT(static_cast<BinaryOpNode*>(right)->opcodeID() == op_urshift);
2126 static_cast<BinaryOpNode*>(right)->m_shouldToUnsignedResult = false;
2127 }
2128 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
2129 RefPtr<RegisterID> src2 = generator.emitNode(right);
2130 generator.emitExpressionInfo(position(), position(), position());
2131
2132 // Since the both sides only accept Int32, replacing operands is not observable to users.
2133 bool replaceOperands = false;
2134 OpcodeID resultOp = opcodeID;
2135 switch (opcodeID) {
2136 case op_less:
2137 resultOp = op_below;
2138 break;
2139 case op_lesseq:
2140 resultOp = op_beloweq;
2141 break;
2142 case op_greater:
2143 resultOp = op_below;
2144 replaceOperands = true;
2145 break;
2146 case op_greatereq:
2147 resultOp = op_beloweq;
2148 replaceOperands = true;
2149 break;
2150 default:
2151 RELEASE_ASSERT_NOT_REACHED();
2152 }
2153 OperandTypes operandTypes(left->resultDescriptor(), right->resultDescriptor());
2154 if (replaceOperands) {
2155 std::swap(src1, src2);
2156 operandTypes = OperandTypes(right->resultDescriptor(), left->resultDescriptor());
2157 }
2158 return generator.emitBinaryOp(resultOp, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), operandTypes);
2159 }
2160 }
2161
2162 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
2163 generator.emitExpressionInfo(position(), position(), position());
2164 return emitStrcat(generator, dst);
2165 }
2166
2167 if (opcodeID == op_neq) {
2168 if (m_expr1->isNull() || m_expr2->isNull()) {
2169 RefPtr<RegisterID> src = generator.tempDestination(dst);
2170 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
2171 return generator.emitUnaryOp<OpNeqNull>(generator.finalDestination(dst, src.get()), src.get());
2172 }
2173 }
2174
2175 ExpressionNode* left = m_expr1;
2176 ExpressionNode* right = m_expr2;
2177 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
2178 if (left->isString())
2179 std::swap(left, right);
2180 }
2181
2182 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
2183 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
2184 RefPtr<RegisterID> src2 = generator.emitNode(right);
2185 generator.emitExpressionInfo(position(), position(), position());
2186 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
2187 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
2188 if (opcodeID == op_neq)
2189 generator.emitEqualityOp<OpEq>(generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
2190 else if (opcodeID == op_nstricteq)
2191 generator.emitEqualityOp<OpStricteq>(generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
2192 else
2193 RELEASE_ASSERT_NOT_REACHED();
2194 return generator.emitUnaryOp<OpNot>(generator.finalDestination(dst, tmp.get()), tmp.get());
2195 }
2196 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
2197 if (m_shouldToUnsignedResult) {
2198 if (opcodeID == op_urshift && dst != generator.ignoredResult())
2199 return generator.emitUnaryOp<OpUnsigned>(result, result);
2200 }
2201 return result;
2202}
2203
2204RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2205{
2206 if (m_expr1->isNull() || m_expr2->isNull()) {
2207 RefPtr<RegisterID> src = generator.tempDestination(dst);
2208 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
2209 return generator.emitUnaryOp<OpEqNull>(generator.finalDestination(dst, src.get()), src.get());
2210 }
2211
2212 ExpressionNode* left = m_expr1;
2213 ExpressionNode* right = m_expr2;
2214 if (left->isString())
2215 std::swap(left, right);
2216
2217 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
2218 RefPtr<RegisterID> src2 = generator.emitNode(right);
2219 return generator.emitEqualityOp<OpEq>(generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
2220}
2221
2222RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2223{
2224 ExpressionNode* left = m_expr1;
2225 ExpressionNode* right = m_expr2;
2226 if (left->isString())
2227 std::swap(left, right);
2228
2229 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
2230 RefPtr<RegisterID> src2 = generator.emitNode(right);
2231 return generator.emitEqualityOp<OpStricteq>(generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
2232}
2233
2234RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2235{
2236 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2237 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
2238 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2239 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
2240}
2241
2242RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2243{
2244 RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
2245 RefPtr<RegisterID> isObject = generator.newTemporary();
2246 RefPtr<RegisterID> isCustom = generator.newTemporary();
2247 RefPtr<RegisterID> prototype = generator.newTemporary();
2248 RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2249 RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
2250 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
2251 Ref<Label> custom = generator.newLabel();
2252 Ref<Label> done = generator.newLabel();
2253 Ref<Label> typeError = generator.newLabel();
2254
2255 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2256 generator.emitIsObject(isObject.get(), constructor.get());
2257 generator.emitJumpIfFalse(isObject.get(), typeError.get());
2258
2259 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2260 generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
2261
2262 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2263 generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
2264
2265 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2266 generator.emitJumpIfTrue(isCustom.get(), custom.get());
2267
2268 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2269 generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
2270
2271 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2272 generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
2273
2274 generator.emitJump(done.get());
2275
2276 generator.emitLabel(typeError.get());
2277 generator.emitThrowTypeError("Right hand side of instanceof is not an object");
2278
2279 generator.emitLabel(custom.get());
2280
2281 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2282 generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
2283
2284 generator.emitLabel(done.get());
2285
2286 return dstReg.get();
2287}
2288
2289// ------------------------------ InNode ----------------------------
2290
2291RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2292{
2293 if (isNonIndexStringElement(*m_expr1)) {
2294 RefPtr<RegisterID> base = generator.emitNode(m_expr2);
2295 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2296 return generator.emitInById(generator.finalDestination(dst, base.get()), base.get(), static_cast<StringNode*>(m_expr1)->value());
2297 }
2298
2299 RefPtr<RegisterID> key = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2300 RefPtr<RegisterID> base = generator.emitNode(m_expr2);
2301 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2302 return generator.emitInByVal(generator.finalDestination(dst, key.get()), key.get(), base.get());
2303}
2304
2305
2306// ------------------------------ LogicalOpNode ----------------------------
2307
2308RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2309{
2310 RefPtr<RegisterID> temp = generator.tempDestination(dst);
2311 Ref<Label> target = generator.newLabel();
2312
2313 generator.emitNode(temp.get(), m_expr1);
2314 if (m_operator == OpLogicalAnd)
2315 generator.emitJumpIfFalse(temp.get(), target.get());
2316 else
2317 generator.emitJumpIfTrue(temp.get(), target.get());
2318 generator.emitNodeInTailPosition(temp.get(), m_expr2);
2319 generator.emitLabel(target.get());
2320
2321 return generator.move(dst, temp.get());
2322}
2323
2324void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
2325{
2326 if (UNLIKELY(needsDebugHook()))
2327 generator.emitDebugHook(this);
2328
2329 Ref<Label> afterExpr1 = generator.newLabel();
2330 if (m_operator == OpLogicalAnd)
2331 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
2332 else
2333 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
2334 generator.emitLabel(afterExpr1.get());
2335
2336 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
2337}
2338
2339// ------------------------------ ConditionalNode ------------------------------
2340
2341RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2342{
2343 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
2344 Ref<Label> beforeElse = generator.newLabel();
2345 Ref<Label> afterElse = generator.newLabel();
2346
2347 Ref<Label> beforeThen = generator.newLabel();
2348 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
2349 generator.emitLabel(beforeThen.get());
2350
2351 generator.emitProfileControlFlow(m_expr1->startOffset());
2352 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
2353 generator.emitJump(afterElse.get());
2354
2355 generator.emitLabel(beforeElse.get());
2356 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
2357 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
2358
2359 generator.emitLabel(afterElse.get());
2360
2361 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
2362
2363 return newDst.get();
2364}
2365
2366// ------------------------------ ReadModifyResolveNode -----------------------------------
2367
2368// FIXME: should this be moved to be a method on BytecodeGenerator?
2369static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
2370{
2371 OpcodeID opcodeID;
2372 switch (oper) {
2373 case OpMultEq:
2374 opcodeID = op_mul;
2375 break;
2376 case OpDivEq:
2377 opcodeID = op_div;
2378 break;
2379 case OpPlusEq:
2380 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
2381 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
2382 opcodeID = op_add;
2383 break;
2384 case OpMinusEq:
2385 opcodeID = op_sub;
2386 break;
2387 case OpLShift:
2388 opcodeID = op_lshift;
2389 break;
2390 case OpRShift:
2391 opcodeID = op_rshift;
2392 break;
2393 case OpURShift:
2394 opcodeID = op_urshift;
2395 break;
2396 case OpAndEq:
2397 opcodeID = op_bitand;
2398 break;
2399 case OpXOrEq:
2400 opcodeID = op_bitxor;
2401 break;
2402 case OpOrEq:
2403 opcodeID = op_bitor;
2404 break;
2405 case OpModEq:
2406 opcodeID = op_mod;
2407 break;
2408 case OpPowEq:
2409 opcodeID = op_pow;
2410 break;
2411 default:
2412 RELEASE_ASSERT_NOT_REACHED();
2413 return dst;
2414 }
2415
2416 RegisterID* src2 = generator.emitNode(m_right);
2417
2418 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2419 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2420 if (emitExpressionInfoForMe)
2421 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
2422 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
2423 if (oper == OpURShift)
2424 return generator.emitUnaryOp<OpUnsigned>(result, result);
2425 return result;
2426}
2427
2428RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2429{
2430 JSTextPosition newDivot = divotStart() + m_ident.length();
2431 Variable var = generator.variable(m_ident);
2432 if (RegisterID* local = var.local()) {
2433 generator.emitTDZCheckIfNecessary(var, local, nullptr);
2434 if (var.isReadOnly()) {
2435 generator.emitReadOnlyExceptionIfNeeded(var);
2436 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2437 generator.emitProfileType(result, divotStart(), divotEnd());
2438 return result;
2439 }
2440
2441 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
2442 RefPtr<RegisterID> result = generator.newTemporary();
2443 generator.move(result.get(), local);
2444 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2445 generator.move(local, result.get());
2446 generator.emitProfileType(local, divotStart(), divotEnd());
2447 return generator.move(dst, result.get());
2448 }
2449
2450 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2451 generator.emitProfileType(result, divotStart(), divotEnd());
2452 return generator.move(dst, result);
2453 }
2454
2455 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
2456 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2457 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
2458 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
2459 if (var.isReadOnly()) {
2460 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2461 if (threwException)
2462 return value.get();
2463 }
2464 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
2465 RegisterID* returnResult = result.get();
2466 if (!var.isReadOnly()) {
2467 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
2468 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2469 }
2470 return returnResult;
2471}
2472
2473static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
2474{
2475 switch (assignmentContext) {
2476 case AssignmentContext::DeclarationStatement:
2477 return InitializationMode::Initialization;
2478 case AssignmentContext::ConstDeclarationStatement:
2479 return InitializationMode::ConstInitialization;
2480 case AssignmentContext::AssignmentExpression:
2481 return InitializationMode::NotInitialization;
2482 }
2483
2484 ASSERT_NOT_REACHED();
2485 return InitializationMode::NotInitialization;
2486}
2487
2488// ------------------------------ AssignResolveNode -----------------------------------
2489
2490RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2491{
2492 Variable var = generator.variable(m_ident);
2493 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
2494 if (RegisterID* local = var.local()) {
2495 RegisterID* result = nullptr;
2496 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2497 generator.emitTDZCheckIfNecessary(var, local, nullptr);
2498
2499 if (isReadOnly) {
2500 result = generator.emitNode(dst, m_right); // Execute side effects first.
2501 generator.emitReadOnlyExceptionIfNeeded(var);
2502 generator.emitProfileType(result, var, divotStart(), divotEnd());
2503 } else if (var.isSpecial()) {
2504 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
2505 generator.emitNode(tempDst.get(), m_right);
2506 generator.move(local, tempDst.get());
2507 generator.emitProfileType(local, var, divotStart(), divotEnd());
2508 result = generator.move(dst, tempDst.get());
2509 } else {
2510 RegisterID* right = generator.emitNode(local, m_right);
2511 generator.emitProfileType(right, var, divotStart(), divotEnd());
2512 result = generator.move(dst, right);
2513 }
2514
2515 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
2516 generator.liftTDZCheckIfPossible(var);
2517 return result;
2518 }
2519
2520 if (generator.isStrictMode())
2521 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2522 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2523 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2524 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
2525 if (dst == generator.ignoredResult())
2526 dst = 0;
2527 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
2528 if (isReadOnly) {
2529 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
2530 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2531 if (threwException)
2532 return result;
2533 }
2534 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2535 RegisterID* returnResult = result.get();
2536 if (!isReadOnly) {
2537 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
2538 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2539 }
2540
2541 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
2542 generator.liftTDZCheckIfPossible(var);
2543 return returnResult;
2544}
2545
2546// ------------------------------ AssignDotNode -----------------------------------
2547
2548RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2549{
2550 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2551 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
2552 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
2553 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2554 RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.move(generator.tempDestination(result.get()), result.get());
2555 if (m_base->isSuperNode()) {
2556 RefPtr<RegisterID> thisValue = generator.ensureThis();
2557 generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
2558 } else
2559 generator.emitPutById(base.get(), m_ident, forwardResult.get());
2560 generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
2561 return generator.move(dst, forwardResult.get());
2562}
2563
2564// ------------------------------ ReadModifyDotNode -----------------------------------
2565
2566RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2567{
2568 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2569
2570 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
2571 RefPtr<RegisterID> value;
2572 RefPtr<RegisterID> thisValue;
2573 if (m_base->isSuperNode()) {
2574 thisValue = generator.ensureThis();
2575 value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
2576 } else
2577 value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
2578 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()));
2579
2580 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2581 RegisterID* ret;
2582 if (m_base->isSuperNode())
2583 ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
2584 else
2585 ret = generator.emitPutById(base.get(), m_ident, updatedValue);
2586 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
2587 return ret;
2588}
2589
2590// ------------------------------ AssignErrorNode -----------------------------------
2591
2592RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2593{
2594 return emitThrowReferenceError(generator, "Left side of assignment is not a reference."_s);
2595}
2596
2597// ------------------------------ AssignBracketNode -----------------------------------
2598
2599RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2600{
2601 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2602 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2603 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
2604 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
2605
2606 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2607 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.move(generator.tempDestination(result.get()), result.get());
2608
2609 if (isNonIndexStringElement(*m_subscript)) {
2610 if (m_base->isSuperNode()) {
2611 RefPtr<RegisterID> thisValue = generator.ensureThis();
2612 generator.emitPutById(base.get(), thisValue.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2613 } else
2614 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2615 } else {
2616 if (m_base->isSuperNode()) {
2617 RefPtr<RegisterID> thisValue = generator.ensureThis();
2618 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), forwardResult);
2619 } else
2620 generator.emitPutByVal(base.get(), property.get(), forwardResult);
2621 }
2622
2623 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
2624 return generator.move(dst, forwardResult);
2625}
2626
2627// ------------------------------ ReadModifyBracketNode -----------------------------------
2628
2629RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2630{
2631 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2632 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2633
2634 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
2635 RefPtr<RegisterID> value;
2636 RefPtr<RegisterID> thisValue;
2637 if (m_base->isSuperNode()) {
2638 thisValue = generator.ensureThis();
2639 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisValue.get(), property.get());
2640 } else
2641 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
2642 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()));
2643
2644 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2645 if (m_base->isSuperNode())
2646 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), updatedValue);
2647 else
2648 generator.emitPutByVal(base.get(), property.get(), updatedValue);
2649 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
2650
2651 return updatedValue;
2652}
2653
2654// ------------------------------ CommaNode ------------------------------------
2655
2656RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2657{
2658 CommaNode* node = this;
2659 for (; node && node->next(); node = node->next())
2660 generator.emitNode(generator.ignoredResult(), node->m_expr);
2661 return generator.emitNodeInTailPosition(dst, node->m_expr);
2662}
2663
2664// ------------------------------ SourceElements -------------------------------
2665
2666inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2667{
2668 StatementNode* lastStatementWithCompletionValue = nullptr;
2669 if (generator.shouldBeConcernedWithCompletionValue()) {
2670 for (StatementNode* statement = m_head; statement; statement = statement->next()) {
2671 if (statement->hasCompletionValue())
2672 lastStatementWithCompletionValue = statement;
2673 }
2674 }
2675
2676 for (StatementNode* statement = m_head; statement; statement = statement->next()) {
2677 if (statement == lastStatementWithCompletionValue)
2678 generator.emitLoad(dst, jsUndefined());
2679 generator.emitNodeInTailPosition(dst, statement);
2680 }
2681}
2682
2683// ------------------------------ BlockNode ------------------------------------
2684
2685void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2686{
2687 if (!m_statements)
2688 return;
2689 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
2690 m_statements->emitBytecode(generator, dst);
2691 generator.popLexicalScope(this);
2692}
2693
2694// ------------------------------ EmptyStatementNode ---------------------------
2695
2696void EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2697{
2698 RELEASE_ASSERT(needsDebugHook());
2699}
2700
2701// ------------------------------ DebuggerStatementNode ---------------------------
2702
2703void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2704{
2705 generator.emitDebugHook(DidReachBreakpoint, position());
2706}
2707
2708// ------------------------------ ExprStatementNode ----------------------------
2709
2710void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2711{
2712 ASSERT(m_expr);
2713 generator.emitNode(dst, m_expr);
2714}
2715
2716// ------------------------------ DeclarationStatement ----------------------------
2717
2718void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2719{
2720 ASSERT(m_expr);
2721 generator.emitNode(m_expr);
2722}
2723
2724// ------------------------------ EmptyVarExpression ----------------------------
2725
2726RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2727{
2728 // It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
2729 if (!generator.vm()->typeProfiler())
2730 return nullptr;
2731
2732 Variable var = generator.variable(m_ident);
2733 if (RegisterID* local = var.local())
2734 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2735 else {
2736 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2737 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
2738 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2739 }
2740
2741 return nullptr;
2742}
2743
2744// ------------------------------ EmptyLetExpression ----------------------------
2745
2746RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2747{
2748 // Lexical declarations like 'let' must move undefined into their variables so we don't
2749 // get TDZ errors for situations like this: `let x; x;`
2750 Variable var = generator.variable(m_ident);
2751 if (RegisterID* local = var.local()) {
2752 generator.emitLoad(local, jsUndefined());
2753 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2754 } else {
2755 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2756 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
2757 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
2758 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2759 }
2760
2761 generator.liftTDZCheckIfPossible(var);
2762
2763 // It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
2764 return nullptr;
2765}
2766
2767// ------------------------------ IfElseNode ---------------------------------------
2768
2769static inline StatementNode* singleStatement(StatementNode* statementNode)
2770{
2771 if (statementNode->isBlock())
2772 return static_cast<BlockNode*>(statementNode)->singleStatement();
2773 return statementNode;
2774}
2775
2776bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2777 Label*& trueTarget, FallThroughMode& fallThroughMode)
2778{
2779 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2780 if (!singleStatement)
2781 return false;
2782
2783 if (singleStatement->isBreak()) {
2784 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2785 Label* target = breakNode->trivialTarget(generator);
2786 if (!target)
2787 return false;
2788 trueTarget = target;
2789 fallThroughMode = FallThroughMeansFalse;
2790 return true;
2791 }
2792
2793 if (singleStatement->isContinue()) {
2794 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2795 Label* target = continueNode->trivialTarget(generator);
2796 if (!target)
2797 return false;
2798 trueTarget = target;
2799 fallThroughMode = FallThroughMeansFalse;
2800 return true;
2801 }
2802
2803 return false;
2804}
2805
2806void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2807{
2808 if (generator.shouldBeConcernedWithCompletionValue()) {
2809 if (m_ifBlock->hasEarlyBreakOrContinue() || (m_elseBlock && m_elseBlock->hasEarlyBreakOrContinue()))
2810 generator.emitLoad(dst, jsUndefined());
2811 }
2812
2813 Ref<Label> beforeThen = generator.newLabel();
2814 Ref<Label> beforeElse = generator.newLabel();
2815 Ref<Label> afterElse = generator.newLabel();
2816
2817 Label* trueTarget = beforeThen.ptr();
2818 Label& falseTarget = beforeElse.get();
2819 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2820 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2821
2822 generator.emitNodeInConditionContext(m_condition, *trueTarget, falseTarget, fallThroughMode);
2823 generator.emitLabel(beforeThen.get());
2824 generator.emitProfileControlFlow(m_ifBlock->startOffset());
2825
2826 if (!didFoldIfBlock) {
2827 generator.emitNodeInTailPosition(dst, m_ifBlock);
2828 if (m_elseBlock)
2829 generator.emitJump(afterElse.get());
2830 }
2831
2832 generator.emitLabel(beforeElse.get());
2833
2834 if (m_elseBlock) {
2835 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
2836 generator.emitNodeInTailPosition(dst, m_elseBlock);
2837 }
2838
2839 generator.emitLabel(afterElse.get());
2840 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2841 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
2842}
2843
2844// ------------------------------ DoWhileNode ----------------------------------
2845
2846void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2847{
2848 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
2849 generator.emitLoad(dst, jsUndefined());
2850
2851 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
2852
2853 Ref<Label> topOfLoop = generator.newLabel();
2854 generator.emitLabel(topOfLoop.get());
2855 generator.emitLoopHint();
2856
2857 generator.emitNodeInTailPosition(dst, m_statement);
2858
2859 generator.emitLabel(*scope->continueTarget());
2860 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2861
2862 generator.emitLabel(scope->breakTarget());
2863}
2864
2865// ------------------------------ WhileNode ------------------------------------
2866
2867void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2868{
2869 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
2870 generator.emitLoad(dst, jsUndefined());
2871
2872 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
2873 Ref<Label> topOfLoop = generator.newLabel();
2874
2875 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
2876
2877 generator.emitLabel(topOfLoop.get());
2878 generator.emitLoopHint();
2879
2880 generator.emitProfileControlFlow(m_statement->startOffset());
2881 generator.emitNodeInTailPosition(dst, m_statement);
2882
2883 generator.emitLabel(*scope->continueTarget());
2884
2885 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2886
2887 generator.emitLabel(scope->breakTarget());
2888
2889 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
2890}
2891
2892// ------------------------------ ForNode --------------------------------------
2893
2894void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2895{
2896 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
2897 generator.emitLoad(dst, jsUndefined());
2898
2899 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
2900
2901 RegisterID* forLoopSymbolTable = nullptr;
2902 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
2903
2904 if (m_expr1)
2905 generator.emitNode(generator.ignoredResult(), m_expr1);
2906
2907 Ref<Label> topOfLoop = generator.newLabel();
2908 if (m_expr2)
2909 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
2910
2911 generator.emitLabel(topOfLoop.get());
2912 generator.emitLoopHint();
2913 generator.emitProfileControlFlow(m_statement->startOffset());
2914
2915 generator.emitNodeInTailPosition(dst, m_statement);
2916
2917 generator.emitLabel(*scope->continueTarget());
2918 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
2919 if (m_expr3)
2920 generator.emitNode(generator.ignoredResult(), m_expr3);
2921
2922 if (m_expr2)
2923 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2924 else
2925 generator.emitJump(topOfLoop.get());
2926
2927 generator.emitLabel(scope->breakTarget());
2928 generator.popLexicalScope(this);
2929 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
2930}
2931
2932// ------------------------------ ForInNode ------------------------------------
2933
2934RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
2935{
2936 if (m_lexpr->isResolveNode()) {
2937 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2938 return generator.variable(ident).local();
2939 }
2940
2941 if (m_lexpr->isDestructuringNode()) {
2942 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
2943 auto binding = assignNode->bindings();
2944 if (!binding->isBindingNode())
2945 return nullptr;
2946
2947 auto simpleBinding = static_cast<BindingNode*>(binding);
2948 const Identifier& ident = simpleBinding->boundProperty();
2949 Variable var = generator.variable(ident);
2950 if (var.isSpecial())
2951 return nullptr;
2952 return var.local();
2953 }
2954
2955 return nullptr;
2956}
2957
2958void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2959{
2960 auto lambdaEmitResolveVariable = [&] (const Identifier& ident) {
2961 Variable var = generator.variable(ident);
2962 if (RegisterID* local = var.local()) {
2963 if (var.isReadOnly())
2964 generator.emitReadOnlyExceptionIfNeeded(var);
2965 generator.move(local, propertyName);
2966 } else {
2967 if (generator.isStrictMode())
2968 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2969 if (var.isReadOnly())
2970 generator.emitReadOnlyExceptionIfNeeded(var);
2971 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2972 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2973 generator.emitPutToScope(scope.get(), var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
2974 }
2975 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
2976 };
2977
2978 if (m_lexpr->isResolveNode()) {
2979 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2980 lambdaEmitResolveVariable(ident);
2981 return;
2982 }
2983
2984 if (m_lexpr->isAssignResolveNode()) {
2985 const Identifier& ident = static_cast<AssignResolveNode*>(m_lexpr)->identifier();
2986 lambdaEmitResolveVariable(ident);
2987 return;
2988 }
2989
2990 if (m_lexpr->isDotAccessorNode()) {
2991 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2992 const Identifier& ident = assignNode->identifier();
2993 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2994 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2995 if (assignNode->base()->isSuperNode()) {
2996 RefPtr<RegisterID> thisValue = generator.ensureThis();
2997 generator.emitPutById(base.get(), thisValue.get(), ident, propertyName);
2998 } else
2999 generator.emitPutById(base.get(), ident, propertyName);
3000 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
3001 return;
3002 }
3003 if (m_lexpr->isBracketAccessorNode()) {
3004 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
3005 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3006 RefPtr<RegisterID> subscript = generator.emitNodeForProperty(assignNode->subscript());
3007 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
3008 if (assignNode->base()->isSuperNode()) {
3009 RefPtr<RegisterID> thisValue = generator.ensureThis();
3010 generator.emitPutByVal(base.get(), thisValue.get(), subscript.get(), propertyName);
3011 } else
3012 generator.emitPutByVal(base.get(), subscript.get(), propertyName);
3013 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
3014 return;
3015 }
3016
3017 if (m_lexpr->isDestructuringNode()) {
3018 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
3019 auto binding = assignNode->bindings();
3020 if (!binding->isBindingNode()) {
3021 assignNode->bindings()->bindValue(generator, propertyName);
3022 return;
3023 }
3024
3025 auto simpleBinding = static_cast<BindingNode*>(binding);
3026 const Identifier& ident = simpleBinding->boundProperty();
3027 Variable var = generator.variable(ident);
3028 if (!var.local() || var.isSpecial()) {
3029 assignNode->bindings()->bindValue(generator, propertyName);
3030 return;
3031 }
3032 generator.move(var.local(), propertyName);
3033 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
3034 return;
3035 }
3036
3037 RELEASE_ASSERT_NOT_REACHED();
3038}
3039
3040void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3041{
3042 if (!m_lexpr->isAssignResolveNode() && !m_lexpr->isAssignmentLocation()) {
3043 emitThrowReferenceError(generator, "Left side of for-in statement is not a reference."_s);
3044 return;
3045 }
3046
3047 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
3048 generator.emitLoad(dst, jsUndefined());
3049
3050 Ref<Label> end = generator.newLabel();
3051
3052 RegisterID* forLoopSymbolTable = nullptr;
3053 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
3054
3055 if (m_lexpr->isAssignResolveNode())
3056 generator.emitNode(generator.ignoredResult(), m_lexpr);
3057
3058 RefPtr<RegisterID> base = generator.newTemporary();
3059 RefPtr<RegisterID> length;
3060 RefPtr<RegisterID> enumerator;
3061
3062 generator.emitNode(base.get(), m_expr);
3063 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
3064 RefPtr<RegisterID> enumeratorIndex;
3065
3066 // Pause at the assignment expression for each for..in iteration.
3067 generator.emitDebugHook(m_lexpr);
3068
3069 int profilerStartOffset = m_statement->startOffset();
3070 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
3071
3072 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
3073
3074 BytecodeGenerator::PreservedTDZStack preservedTDZStack;
3075 generator.preserveTDZStack(preservedTDZStack);
3076
3077 // Indexed property loop.
3078 {
3079 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
3080 Ref<Label> loopStart = generator.newLabel();
3081 Ref<Label> loopEnd = generator.newLabel();
3082
3083 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
3084 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
3085 RefPtr<RegisterID> propertyName = generator.newTemporary();
3086
3087 generator.emitLabel(loopStart.get());
3088 generator.emitLoopHint();
3089
3090 RefPtr<RegisterID> result = generator.emitEqualityOp<OpLess>(generator.newTemporary(), i.get(), length.get());
3091 generator.emitJumpIfFalse(result.get(), loopEnd.get());
3092 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
3093 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
3094
3095 generator.emitToIndexString(propertyName.get(), i.get());
3096 this->emitLoopHeader(generator, propertyName.get());
3097
3098 generator.emitProfileControlFlow(profilerStartOffset);
3099
3100 generator.pushIndexedForInScope(local.get(), i.get());
3101 generator.emitNode(dst, m_statement);
3102 generator.popIndexedForInScope(local.get());
3103
3104 generator.emitProfileControlFlow(profilerEndOffset);
3105
3106 generator.emitLabel(*scope->continueTarget());
3107 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
3108 generator.emitInc(i.get());
3109 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
3110 generator.emitJump(loopStart.get());
3111
3112 generator.emitLabel(scope->breakTarget());
3113 generator.emitJump(end.get());
3114 generator.emitLabel(loopEnd.get());
3115 }
3116 generator.restoreTDZStack(preservedTDZStack);
3117
3118 // Structure property loop.
3119 {
3120 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
3121 Ref<Label> loopStart = generator.newLabel();
3122 Ref<Label> loopEnd = generator.newLabel();
3123
3124 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
3125 RefPtr<RegisterID> propertyName = generator.newTemporary();
3126 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3127
3128 generator.emitLabel(loopStart.get());
3129 generator.emitLoopHint();
3130
3131 RefPtr<RegisterID> result = generator.emitUnaryOp<OpEqNull>(generator.newTemporary(), propertyName.get());
3132 generator.emitJumpIfTrue(result.get(), loopEnd.get());
3133 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
3134 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
3135
3136 this->emitLoopHeader(generator, propertyName.get());
3137
3138 generator.emitProfileControlFlow(profilerStartOffset);
3139
3140 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
3141 generator.emitNode(dst, m_statement);
3142 generator.popStructureForInScope(local.get());
3143
3144 generator.emitProfileControlFlow(profilerEndOffset);
3145
3146 generator.emitLabel(*scope->continueTarget());
3147 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
3148 generator.emitInc(enumeratorIndex.get());
3149 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3150 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
3151 generator.emitJump(loopStart.get());
3152
3153 generator.emitLabel(scope->breakTarget());
3154 generator.emitJump(end.get());
3155 generator.emitLabel(loopEnd.get());
3156 }
3157 generator.restoreTDZStack(preservedTDZStack);
3158
3159 // Generic property loop.
3160 {
3161 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
3162 Ref<Label> loopStart = generator.newLabel();
3163 Ref<Label> loopEnd = generator.newLabel();
3164
3165 RefPtr<RegisterID> propertyName = generator.newTemporary();
3166
3167 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3168
3169 generator.emitLabel(loopStart.get());
3170 generator.emitLoopHint();
3171
3172 RefPtr<RegisterID> result = generator.emitUnaryOp<OpEqNull>(generator.newTemporary(), propertyName.get());
3173 generator.emitJumpIfTrue(result.get(), loopEnd.get());
3174
3175 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
3176 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
3177
3178 this->emitLoopHeader(generator, propertyName.get());
3179
3180 generator.emitProfileControlFlow(profilerStartOffset);
3181
3182 generator.emitNode(dst, m_statement);
3183
3184 generator.emitLabel(*scope->continueTarget());
3185 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
3186 generator.emitInc(enumeratorIndex.get());
3187 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3188 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
3189 generator.emitJump(loopStart.get());
3190
3191 generator.emitLabel(scope->breakTarget());
3192 generator.emitJump(end.get());
3193 generator.emitLabel(loopEnd.get());
3194 }
3195
3196 generator.emitLabel(end.get());
3197 generator.popLexicalScope(this);
3198 generator.emitProfileControlFlow(profilerEndOffset);
3199}
3200
3201// ------------------------------ ForOfNode ------------------------------------
3202void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3203{
3204 if (!m_lexpr->isAssignmentLocation()) {
3205 emitThrowReferenceError(generator, "Left side of for-of statement is not a reference."_s);
3206 return;
3207 }
3208
3209 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
3210 generator.emitLoad(dst, jsUndefined());
3211
3212 RegisterID* forLoopSymbolTable = nullptr;
3213 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
3214 auto extractor = scopedLambda<void(BytecodeGenerator&, RegisterID*)>([this, dst](BytecodeGenerator& generator, RegisterID* value)
3215 {
3216 if (m_lexpr->isResolveNode()) {
3217 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
3218 Variable var = generator.variable(ident);
3219 if (RegisterID* local = var.local()) {
3220 if (var.isReadOnly())
3221 generator.emitReadOnlyExceptionIfNeeded(var);
3222 generator.move(local, value);
3223 } else {
3224 if (generator.isStrictMode())
3225 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
3226 if (var.isReadOnly())
3227 generator.emitReadOnlyExceptionIfNeeded(var);
3228 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
3229 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
3230 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
3231 }
3232 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
3233 } else if (m_lexpr->isDotAccessorNode()) {
3234 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
3235 const Identifier& ident = assignNode->identifier();
3236 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3237
3238 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
3239 if (assignNode->base()->isSuperNode()) {
3240 RefPtr<RegisterID> thisValue = generator.ensureThis();
3241 generator.emitPutById(base.get(), thisValue.get(), ident, value);
3242 } else
3243 generator.emitPutById(base.get(), ident, value);
3244 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
3245 } else if (m_lexpr->isBracketAccessorNode()) {
3246 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
3247 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3248 RegisterID* subscript = generator.emitNodeForProperty(assignNode->subscript());
3249
3250 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
3251 if (assignNode->base()->isSuperNode()) {
3252 RefPtr<RegisterID> thisValue = generator.ensureThis();
3253 generator.emitPutByVal(base.get(), thisValue.get(), subscript, value);
3254 } else
3255 generator.emitPutByVal(base.get(), subscript, value);
3256 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
3257 } else {
3258 ASSERT(m_lexpr->isDestructuringNode());
3259 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
3260 assignNode->bindings()->bindValue(generator, value);
3261 }
3262 generator.emitProfileControlFlow(m_statement->startOffset());
3263 generator.emitNode(dst, m_statement);
3264 });
3265 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
3266 generator.popLexicalScope(this);
3267 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
3268}
3269
3270// ------------------------------ ContinueNode ---------------------------------
3271
3272Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
3273{
3274 if (generator.shouldEmitDebugHooks())
3275 return nullptr;
3276
3277 LabelScope* scope = generator.continueTarget(m_ident);
3278 ASSERT(scope);
3279
3280 if (generator.labelScopeDepth() != scope->scopeDepth())
3281 return nullptr;
3282
3283 return scope->continueTarget();
3284}
3285
3286void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3287{
3288 LabelScope* scope = generator.continueTarget(m_ident);
3289 ASSERT(scope);
3290
3291 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), *scope->continueTarget());
3292 if (!hasFinally) {
3293 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3294 generator.restoreScopeRegister(lexicalScopeIndex);
3295 generator.emitJump(*scope->continueTarget());
3296 }
3297
3298 generator.emitProfileControlFlow(endOffset());
3299}
3300
3301// ------------------------------ BreakNode ------------------------------------
3302
3303Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
3304{
3305 if (generator.shouldEmitDebugHooks())
3306 return nullptr;
3307
3308 LabelScope* scope = generator.breakTarget(m_ident);
3309 ASSERT(scope);
3310
3311 if (generator.labelScopeDepth() != scope->scopeDepth())
3312 return nullptr;
3313
3314 return &scope->breakTarget();
3315}
3316
3317void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3318{
3319 LabelScope* scope = generator.breakTarget(m_ident);
3320 ASSERT(scope);
3321
3322 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget());
3323 if (!hasFinally) {
3324 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3325 generator.restoreScopeRegister(lexicalScopeIndex);
3326 generator.emitJump(scope->breakTarget());
3327 }
3328
3329 generator.emitProfileControlFlow(endOffset());
3330}
3331
3332// ------------------------------ ReturnNode -----------------------------------
3333
3334void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3335{
3336 ASSERT(generator.codeType() == FunctionCode);
3337
3338 if (dst == generator.ignoredResult())
3339 dst = 0;
3340
3341 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
3342
3343 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
3344
3345 bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());
3346 if (!hasFinally) {
3347 if (generator.parseMode() == SourceParseMode::AsyncGeneratorBodyMode) {
3348 returnRegister = generator.move(generator.newTemporary(), returnRegister.get());
3349 generator.emitAwait(returnRegister.get());
3350 }
3351
3352 generator.emitWillLeaveCallFrameDebugHook();
3353 generator.emitReturn(returnRegister.get());
3354 }
3355
3356 generator.emitProfileControlFlow(endOffset());
3357 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
3358 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
3359 if (generator.vm()->controlFlowProfiler())
3360 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
3361}
3362
3363// ------------------------------ WithNode -------------------------------------
3364
3365void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3366{
3367 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
3368 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
3369 generator.emitPushWithScope(scope.get());
3370 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
3371 generator.emitLoad(dst, jsUndefined());
3372 generator.emitNodeInTailPosition(dst, m_statement);
3373 generator.emitPopWithScope();
3374}
3375
3376// ------------------------------ CaseClauseNode --------------------------------
3377
3378inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3379{
3380 generator.emitProfileControlFlow(m_startOffset);
3381 if (!m_statements)
3382 return;
3383 m_statements->emitBytecode(generator, dst);
3384}
3385
3386// ------------------------------ CaseBlockNode --------------------------------
3387
3388enum SwitchKind {
3389 SwitchUnset = 0,
3390 SwitchNumber = 1,
3391 SwitchString = 2,
3392 SwitchNeither = 3
3393};
3394
3395static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
3396{
3397 for (; list; list = list->getNext()) {
3398 ExpressionNode* clauseExpression = list->getClause()->expr();
3399 literalVector.append(clauseExpression);
3400 if (clauseExpression->isNumber()) {
3401 double value = static_cast<NumberNode*>(clauseExpression)->value();
3402 int32_t intVal = static_cast<int32_t>(value);
3403 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
3404 typeForTable = SwitchNeither;
3405 break;
3406 }
3407 if (intVal < min_num)
3408 min_num = intVal;
3409 if (intVal > max_num)
3410 max_num = intVal;
3411 typeForTable = SwitchNumber;
3412 continue;
3413 }
3414 if (clauseExpression->isString()) {
3415 if (typeForTable & ~SwitchString) {
3416 typeForTable = SwitchNeither;
3417 break;
3418 }
3419 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
3420 if (singleCharacterSwitch &= value.length() == 1) {
3421 int32_t intVal = value[0];
3422 if (intVal < min_num)
3423 min_num = intVal;
3424 if (intVal > max_num)
3425 max_num = intVal;
3426 }
3427 typeForTable = SwitchString;
3428 continue;
3429 }
3430 typeForTable = SwitchNeither;
3431 break;
3432 }
3433}
3434
3435static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
3436{
3437 size_t length = 0;
3438 for (ClauseListNode* node = list1; node; node = node->getNext())
3439 ++length;
3440 for (ClauseListNode* node = list2; node; node = node->getNext())
3441 ++length;
3442 return length;
3443}
3444
3445SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
3446{
3447 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
3448 return SwitchInfo::SwitchNone;
3449
3450 SwitchKind typeForTable = SwitchUnset;
3451 bool singleCharacterSwitch = true;
3452
3453 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3454 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3455
3456 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
3457 return SwitchInfo::SwitchNone;
3458
3459 if (typeForTable == SwitchNumber) {
3460 int32_t range = max_num - min_num;
3461 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3462 return SwitchInfo::SwitchImmediate;
3463 return SwitchInfo::SwitchNone;
3464 }
3465
3466 ASSERT(typeForTable == SwitchString);
3467
3468 if (singleCharacterSwitch) {
3469 int32_t range = max_num - min_num;
3470 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3471 return SwitchInfo::SwitchCharacter;
3472 }
3473
3474 return SwitchInfo::SwitchString;
3475}
3476
3477void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
3478{
3479 Vector<Ref<Label>, 8> labelVector;
3480 Vector<ExpressionNode*, 8> literalVector;
3481 int32_t min_num = std::numeric_limits<int32_t>::max();
3482 int32_t max_num = std::numeric_limits<int32_t>::min();
3483 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
3484
3485 Ref<Label> defaultLabel = generator.newLabel();
3486 if (switchType != SwitchInfo::SwitchNone) {
3487 // Prepare the various labels
3488 for (uint32_t i = 0; i < literalVector.size(); i++)
3489 labelVector.append(generator.newLabel());
3490 generator.beginSwitch(switchExpression, switchType);
3491 } else {
3492 // Setup jumps
3493 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3494 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3495 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3496 generator.emitBinaryOp<OpStricteq>(clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3497 labelVector.append(generator.newLabel());
3498 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3499 }
3500
3501 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3502 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3503 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3504 generator.emitBinaryOp<OpStricteq>(clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3505 labelVector.append(generator.newLabel());
3506 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3507 }
3508 generator.emitJump(defaultLabel.get());
3509 }
3510
3511 size_t i = 0;
3512 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3513 generator.emitLabel(labelVector[i++].get());
3514 list->getClause()->emitBytecode(generator, dst);
3515 }
3516
3517 if (m_defaultClause) {
3518 generator.emitLabel(defaultLabel.get());
3519 m_defaultClause->emitBytecode(generator, dst);
3520 }
3521
3522 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3523 generator.emitLabel(labelVector[i++].get());
3524 list->getClause()->emitBytecode(generator, dst);
3525 }
3526 if (!m_defaultClause)
3527 generator.emitLabel(defaultLabel.get());
3528
3529 ASSERT(i == labelVector.size());
3530 if (switchType != SwitchInfo::SwitchNone) {
3531 ASSERT(labelVector.size() == literalVector.size());
3532 generator.endSwitch(labelVector.size(), labelVector, literalVector.data(), defaultLabel.get(), min_num, max_num);
3533 }
3534}
3535
3536// ------------------------------ SwitchNode -----------------------------------
3537
3538void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3539{
3540 if (generator.shouldBeConcernedWithCompletionValue())
3541 generator.emitLoad(dst, jsUndefined());
3542
3543 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
3544
3545 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
3546
3547 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::DoNotOptimize, BytecodeGenerator::NestedScopeType::IsNested);
3548 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
3549 generator.popLexicalScope(this);
3550
3551 generator.emitLabel(scope->breakTarget());
3552 generator.emitProfileControlFlow(endOffset());
3553}
3554
3555// ------------------------------ LabelNode ------------------------------------
3556
3557void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3558{
3559 ASSERT(!generator.breakTarget(m_name));
3560
3561 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
3562 generator.emitNodeInTailPosition(dst, m_statement);
3563
3564 generator.emitLabel(scope->breakTarget());
3565}
3566
3567// ------------------------------ ThrowNode ------------------------------------
3568
3569void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3570{
3571 if (dst == generator.ignoredResult())
3572 dst = 0;
3573 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
3574 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
3575 generator.emitThrow(expr.get());
3576
3577 generator.emitProfileControlFlow(endOffset());
3578}
3579
3580// ------------------------------ TryNode --------------------------------------
3581
3582void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3583{
3584 // NOTE: The catch and finally blocks must be labeled explicitly, so the
3585 // optimizer knows they may be jumped to from anywhere.
3586
3587 if (generator.shouldBeConcernedWithCompletionValue() && m_tryBlock->hasEarlyBreakOrContinue())
3588 generator.emitLoad(dst, jsUndefined());
3589
3590 ASSERT(m_catchBlock || m_finallyBlock);
3591
3592 RefPtr<Label> catchLabel;
3593 RefPtr<Label> catchEndLabel;
3594 RefPtr<Label> finallyLabel;
3595 RefPtr<Label> finallyEndLabel;
3596 Optional<FinallyContext> finallyContext;
3597
3598 if (m_finallyBlock) {
3599 finallyLabel = generator.newLabel();
3600 finallyEndLabel = generator.newLabel();
3601
3602 finallyContext.emplace(generator, *finallyLabel);
3603 generator.pushFinallyControlFlowScope(finallyContext.value());
3604 }
3605 if (m_catchBlock) {
3606 catchLabel = generator.newLabel();
3607 catchEndLabel = generator.newLabel();
3608 }
3609
3610 Ref<Label> tryLabel = generator.newEmittedLabel();
3611 Label& tryHandlerLabel = m_catchBlock ? *catchLabel : *finallyLabel;
3612 HandlerType tryHandlerType = m_catchBlock ? HandlerType::Catch : HandlerType::Finally;
3613 TryData* tryData = generator.pushTry(tryLabel.get(), tryHandlerLabel, tryHandlerType);
3614 TryData* finallyTryData = nullptr;
3615 if (!m_catchBlock && m_finallyBlock)
3616 finallyTryData = tryData;
3617
3618 generator.emitNode(dst, m_tryBlock);
3619
3620 if (m_finallyBlock)
3621 generator.emitJump(*finallyLabel);
3622 else
3623 generator.emitJump(*catchEndLabel);
3624
3625 Ref<Label> tryEndLabel = generator.newEmittedLabel();
3626 generator.popTry(tryData, tryEndLabel.get());
3627
3628 if (m_catchBlock) {
3629 // Uncaught exception path: the catch block.
3630 generator.emitLabel(*catchLabel);
3631 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
3632 RegisterID* completionTypeRegister = m_finallyBlock ? finallyContext->completionTypeRegister() : nullptr;
3633 generator.emitOutOfLineCatchHandler(thrownValueRegister.get(), completionTypeRegister, tryData);
3634 generator.restoreScopeRegister();
3635
3636 if (m_finallyBlock) {
3637 // If the catch block throws an exception and we have a finally block, then the finally
3638 // block should "catch" that exception.
3639 finallyTryData = generator.pushTry(*catchLabel, *finallyLabel, HandlerType::Finally);
3640 }
3641
3642 if (m_catchPattern) {
3643 generator.emitPushCatchScope(m_lexicalVariables);
3644 m_catchPattern->bindValue(generator, thrownValueRegister.get());
3645 }
3646
3647 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
3648 if (m_finallyBlock)
3649 generator.emitNode(dst, m_catchBlock);
3650 else
3651 generator.emitNodeInTailPosition(dst, m_catchBlock);
3652 generator.emitLoad(thrownValueRegister.get(), jsUndefined());
3653
3654 if (m_catchPattern)
3655 generator.emitPopCatchScope(m_lexicalVariables);
3656
3657 if (m_finallyBlock) {
3658 generator.emitLoad(finallyContext->completionTypeRegister(), CompletionType::Normal);
3659 generator.emitJump(*finallyLabel);
3660 generator.popTry(finallyTryData, *finallyLabel);
3661 }
3662
3663 generator.emitLabel(*catchEndLabel);
3664 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
3665 }
3666
3667 if (m_finallyBlock) {
3668 generator.popFinallyControlFlowScope();
3669
3670 // Entry to the finally block for CompletionType::Throw to be generated later.
3671 generator.emitOutOfLineFinallyHandler(finallyContext->completionValueRegister(), finallyContext->completionTypeRegister(), finallyTryData);
3672
3673 // Entry to the finally block for CompletionTypes other than Throw.
3674 generator.emitLabel(*finallyLabel);
3675 generator.restoreScopeRegister();
3676
3677 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
3678 generator.emitProfileControlFlow(finallyStartOffset);
3679 generator.emitNodeInTailPosition(m_finallyBlock);
3680
3681 generator.emitFinallyCompletion(finallyContext.value(), *finallyEndLabel);
3682 generator.emitLabel(*finallyEndLabel);
3683 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
3684 }
3685}
3686
3687// ------------------------------ ScopeNode -----------------------------
3688
3689inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
3690{
3691 if (!m_statements)
3692 return;
3693 m_statements->emitBytecode(generator, dst);
3694}
3695
3696static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
3697{
3698 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
3699
3700 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3701 generator.emitLoad(dstRegister.get(), jsUndefined());
3702 generator.emitProfileControlFlow(scopeNode.startStartOffset());
3703 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
3704
3705 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
3706 generator.emitEnd(dstRegister.get());
3707}
3708
3709// ------------------------------ ProgramNode -----------------------------
3710
3711void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3712{
3713 emitProgramNodeBytecode(generator, *this);
3714}
3715
3716// ------------------------------ ModuleProgramNode --------------------
3717
3718void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3719{
3720 emitProgramNodeBytecode(generator, *this);
3721}
3722
3723// ------------------------------ EvalNode -----------------------------
3724
3725void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3726{
3727 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
3728
3729 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3730 generator.emitLoad(dstRegister.get(), jsUndefined());
3731 emitStatementsBytecode(generator, dstRegister.get());
3732
3733 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
3734 generator.emitEnd(dstRegister.get());
3735}
3736
3737// ------------------------------ FunctionNode -----------------------------
3738
3739void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3740{
3741 if (generator.vm()->typeProfiler()) {
3742 // If the parameter list is non simple one, it is handled in bindValue's code.
3743 if (m_parameters->isSimpleParameterList()) {
3744 for (size_t i = 0; i < m_parameters->size(); i++) {
3745 BindingNode* bindingNode = static_cast<BindingNode*>(m_parameters->at(i).first);
3746 RegisterID reg(CallFrame::argumentOffset(i));
3747 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, bindingNode->divotStart(), bindingNode->divotEnd());
3748 }
3749 }
3750 }
3751
3752 generator.emitProfileControlFlow(startStartOffset());
3753 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
3754
3755 switch (generator.parseMode()) {
3756 case SourceParseMode::GeneratorWrapperFunctionMode:
3757 case SourceParseMode::GeneratorWrapperMethodMode:
3758 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
3759 case SourceParseMode::AsyncGeneratorWrapperFunctionMode: {
3760 StatementNode* singleStatement = this->singleStatement();
3761 ASSERT(singleStatement->isExprStatement());
3762 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3763 ExpressionNode* expr = exprStatement->expr();
3764 ASSERT(expr->isFuncExprNode());
3765 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
3766
3767 RefPtr<RegisterID> next = generator.newTemporary();
3768 generator.emitNode(next.get(), funcExpr);
3769
3770 if (generator.superBinding() == SuperBinding::Needed) {
3771 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3772 emitPutHomeObject(generator, next.get(), homeObject.get());
3773 }
3774
3775 if (isGeneratorWrapperParseMode(generator.parseMode()))
3776 generator.emitPutGeneratorFields(next.get());
3777 else {
3778 ASSERT(isAsyncGeneratorWrapperParseMode(generator.parseMode()));
3779 generator.emitPutAsyncGeneratorFields(next.get());
3780 }
3781
3782 ASSERT(startOffset() >= lineStartOffset());
3783 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3784 generator.emitReturn(generator.generatorRegister());
3785 break;
3786 }
3787
3788 case SourceParseMode::AsyncFunctionMode:
3789 case SourceParseMode::AsyncMethodMode:
3790 case SourceParseMode::AsyncArrowFunctionMode: {
3791 StatementNode* singleStatement = this->singleStatement();
3792 ASSERT(singleStatement->isExprStatement());
3793 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3794 ExpressionNode* expr = exprStatement->expr();
3795 ASSERT(expr->isFuncExprNode());
3796 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
3797
3798 RefPtr<RegisterID> next = generator.newTemporary();
3799 generator.emitNode(next.get(), funcExpr);
3800
3801 if (generator.superBinding() == SuperBinding::Needed || (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isSuperUsedInInnerArrowFunction())) {
3802 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3803 emitPutHomeObject(generator, next.get(), homeObject.get());
3804 }
3805
3806 if (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isThisUsedInInnerArrowFunction())
3807 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
3808
3809 generator.emitPutGeneratorFields(next.get());
3810
3811 ASSERT(startOffset() >= lineStartOffset());
3812 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3813
3814 // load and call @asyncFunctionResume
3815 auto var = generator.variable(generator.propertyNames().builtinNames().asyncFunctionResumePrivateName());
3816 RefPtr<RegisterID> scope = generator.newTemporary();
3817 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
3818 RefPtr<RegisterID> asyncFunctionResume = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
3819
3820 CallArguments args(generator, nullptr, 4);
3821 unsigned argumentCount = 0;
3822 generator.emitLoad(args.thisRegister(), jsUndefined());
3823 generator.move(args.argumentRegister(argumentCount++), generator.generatorRegister());
3824 generator.move(args.argumentRegister(argumentCount++), generator.promiseCapabilityRegister());
3825 generator.emitLoad(args.argumentRegister(argumentCount++), jsUndefined());
3826 generator.emitLoad(args.argumentRegister(argumentCount++), jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
3827 // JSTextPosition(int _line, int _offset, int _lineStartOffset)
3828 JSTextPosition divot(firstLine(), startOffset(), lineStartOffset());
3829
3830 RefPtr<RegisterID> result = generator.newTemporary();
3831 generator.emitCallInTailPosition(result.get(), asyncFunctionResume.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
3832 generator.emitReturn(result.get());
3833 break;
3834 }
3835
3836 case SourceParseMode::AsyncGeneratorBodyMode:
3837 case SourceParseMode::AsyncArrowFunctionBodyMode:
3838 case SourceParseMode::AsyncFunctionBodyMode:
3839 case SourceParseMode::GeneratorBodyMode: {
3840 Ref<Label> generatorBodyLabel = generator.newLabel();
3841 {
3842 RefPtr<RegisterID> condition = generator.newTemporary();
3843 generator.emitEqualityOp<OpStricteq>(condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))));
3844 generator.emitJumpIfTrue(condition.get(), generatorBodyLabel.get());
3845
3846 Ref<Label> throwLabel = generator.newLabel();
3847 generator.emitEqualityOp<OpStricteq>(condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))));
3848 generator.emitJumpIfTrue(condition.get(), throwLabel.get());
3849
3850 generator.emitReturn(generator.generatorValueRegister());
3851
3852 generator.emitLabel(throwLabel.get());
3853 generator.emitThrow(generator.generatorValueRegister());
3854 }
3855
3856 generator.emitLabel(generatorBodyLabel.get());
3857
3858 emitStatementsBytecode(generator, generator.ignoredResult());
3859
3860 Ref<Label> done = generator.newLabel();
3861 generator.emitLabel(done.get());
3862 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
3863 break;
3864 }
3865
3866 default: {
3867 emitStatementsBytecode(generator, generator.ignoredResult());
3868
3869 StatementNode* singleStatement = this->singleStatement();
3870 ReturnNode* returnNode = 0;
3871
3872 // Check for a return statement at the end of a function composed of a single block.
3873 if (singleStatement && singleStatement->isBlock()) {
3874 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
3875 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
3876 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
3877 }
3878
3879 // If there is no return we must automatically insert one.
3880 if (!returnNode) {
3881 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isSuperCallUsedInInnerArrowFunction())
3882 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
3883
3884 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
3885 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
3886 ASSERT(startOffset() >= lineStartOffset());
3887 generator.emitWillLeaveCallFrameDebugHook();
3888 generator.emitReturn(r0);
3889 return;
3890 }
3891 break;
3892 }
3893 }
3894}
3895
3896// ------------------------------ FuncDeclNode ---------------------------------
3897
3898void FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3899{
3900 generator.hoistSloppyModeFunctionIfNecessary(metadata()->ident());
3901}
3902
3903// ------------------------------ FuncExprNode ---------------------------------
3904
3905RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3906{
3907 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3908}
3909
3910// ------------------------------ ArrowFuncExprNode ---------------------------------
3911
3912RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3913{
3914 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3915}
3916
3917// ------------------------------ MethodDefinitionNode ---------------------------------
3918
3919RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3920{
3921 return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
3922}
3923
3924// ------------------------------ YieldExprNode --------------------------------
3925
3926RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3927{
3928 if (!delegate()) {
3929 RefPtr<RegisterID> arg = nullptr;
3930 if (argument()) {
3931 arg = generator.newTemporary();
3932 generator.emitNode(arg.get(), argument());
3933 } else
3934 arg = generator.emitLoad(nullptr, jsUndefined());
3935 RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield);
3936 if (dst == generator.ignoredResult())
3937 return nullptr;
3938 return generator.move(generator.finalDestination(dst), value.get());
3939 }
3940 RefPtr<RegisterID> arg = generator.newTemporary();
3941 generator.emitNode(arg.get(), argument());
3942 RefPtr<RegisterID> value = generator.emitDelegateYield(arg.get(), this);
3943 if (dst == generator.ignoredResult())
3944 return nullptr;
3945 return generator.move(generator.finalDestination(dst), value.get());
3946}
3947
3948// ------------------------------ AwaitExprNode --------------------------------
3949
3950RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3951{
3952 RefPtr<RegisterID> arg = generator.newTemporary();
3953 generator.emitNode(arg.get(), argument());
3954 RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Await);
3955 if (dst == generator.ignoredResult())
3956 return nullptr;
3957 return generator.move(generator.finalDestination(dst), value.get());
3958}
3959
3960// ------------------------------ ClassDeclNode ---------------------------------
3961
3962void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3963{
3964 generator.emitNode(m_classDeclaration);
3965}
3966
3967// ------------------------------ ClassExprNode ---------------------------------
3968
3969RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3970{
3971 if (!m_name.isNull())
3972 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
3973
3974 RefPtr<RegisterID> superclass;
3975 if (m_classHeritage) {
3976 superclass = generator.newTemporary();
3977 generator.emitNode(superclass.get(), m_classHeritage);
3978 }
3979
3980 RefPtr<RegisterID> constructor;
3981 bool needsHomeObject = false;
3982
3983 if (m_constructorExpression) {
3984 ASSERT(m_constructorExpression->isFuncExprNode());
3985 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata();
3986 metadata->setEcmaName(ecmaName());
3987 metadata->setClassSource(m_classSource);
3988 constructor = generator.emitNode(dst, m_constructorExpression);
3989 needsHomeObject = m_classHeritage || metadata->superBinding() == SuperBinding::Needed;
3990 } else
3991 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3992
3993 const auto& propertyNames = generator.propertyNames();
3994 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
3995
3996 if (superclass) {
3997 RefPtr<RegisterID> protoParent = generator.newTemporary();
3998 generator.emitLoad(protoParent.get(), jsNull());
3999
4000 RefPtr<RegisterID> tempRegister = generator.newTemporary();
4001
4002 // FIXME: Throw TypeError if it's a generator function.
4003 Ref<Label> superclassIsUndefinedLabel = generator.newLabel();
4004 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
4005
4006 Ref<Label> superclassIsNullLabel = generator.newLabel();
4007 generator.emitJumpIfTrue(generator.emitUnaryOp<OpEqNull>(tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
4008
4009 Ref<Label> superclassIsObjectLabel = generator.newLabel();
4010 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
4011 generator.emitLabel(superclassIsUndefinedLabel.get());
4012 generator.emitThrowTypeError("The superclass is not an object."_s);
4013 generator.emitLabel(superclassIsObjectLabel.get());
4014 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
4015
4016 Ref<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
4017 generator.emitJumpIfTrue(generator.emitUnaryOp<OpIsObjectOrNull>(tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
4018 generator.emitJumpIfTrue(generator.emitUnaryOp<OpIsFunction>(tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
4019 generator.emitThrowTypeError("The value of the superclass's prototype property is not an object."_s);
4020 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
4021
4022 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
4023 generator.emitLabel(superclassIsNullLabel.get());
4024 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
4025 }
4026
4027 if (needsHomeObject)
4028 emitPutHomeObject(generator, constructor.get(), prototype.get());
4029
4030 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
4031 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
4032 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
4033
4034 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
4035 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
4036
4037 if (m_classElements)
4038 generator.emitDefineClassElements(m_classElements, constructor.get(), prototype.get());
4039
4040 if (!m_name.isNull()) {
4041 Variable classNameVar = generator.variable(m_name);
4042 RELEASE_ASSERT(classNameVar.isResolved());
4043 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
4044 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
4045 generator.popLexicalScope(this);
4046 }
4047
4048 return generator.move(dst, constructor.get());
4049}
4050
4051// ------------------------------ ImportDeclarationNode -----------------------
4052
4053void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4054{
4055 // Do nothing at runtime.
4056}
4057
4058// ------------------------------ ExportAllDeclarationNode --------------------
4059
4060void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4061{
4062 // Do nothing at runtime.
4063}
4064
4065// ------------------------------ ExportDefaultDeclarationNode ----------------
4066
4067void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4068{
4069 ASSERT(m_declaration);
4070 generator.emitNode(dst, m_declaration);
4071}
4072
4073// ------------------------------ ExportLocalDeclarationNode ------------------
4074
4075void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4076{
4077 ASSERT(m_declaration);
4078 generator.emitNode(dst, m_declaration);
4079}
4080
4081// ------------------------------ ExportNamedDeclarationNode ------------------
4082
4083void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4084{
4085 // Do nothing at runtime.
4086}
4087
4088// ------------------------------ DestructuringAssignmentNode -----------------
4089RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4090{
4091 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
4092 return result;
4093 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
4094 generator.emitNode(initializer.get(), m_initializer);
4095 m_bindings->bindValue(generator, initializer.get());
4096 return generator.move(dst, initializer.get());
4097}
4098
4099static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
4100{
4101 ASSERT(defaultValue);
4102 Ref<Label> isNotUndefined = generator.newLabel();
4103 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
4104 generator.emitNode(maybeUndefined, defaultValue);
4105 generator.emitLabel(isNotUndefined.get());
4106}
4107
4108void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
4109{
4110 RefPtr<RegisterID> iterator = generator.newTemporary();
4111 {
4112 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
4113 CallArguments args(generator, nullptr);
4114 generator.move(args.thisRegister(), rhs);
4115 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4116 }
4117 RefPtr<RegisterID> nextMethod = generator.emitGetById(generator.newTemporary(), iterator.get(), generator.propertyNames().next);
4118
4119 if (m_targetPatterns.isEmpty()) {
4120 generator.emitIteratorClose(iterator.get(), this);
4121 return;
4122 }
4123
4124 RefPtr<RegisterID> done;
4125 for (auto& target : m_targetPatterns) {
4126 switch (target.bindingType) {
4127 case BindingType::Elision:
4128 case BindingType::Element: {
4129 Ref<Label> iterationSkipped = generator.newLabel();
4130 if (!done)
4131 done = generator.newTemporary();
4132 else
4133 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
4134
4135 RefPtr<RegisterID> value = generator.newTemporary();
4136 generator.emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), this);
4137 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
4138 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
4139 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
4140
4141 {
4142 Ref<Label> valueIsSet = generator.newLabel();
4143 generator.emitJump(valueIsSet.get());
4144 generator.emitLabel(iterationSkipped.get());
4145 generator.emitLoad(value.get(), jsUndefined());
4146 generator.emitLabel(valueIsSet.get());
4147 }
4148
4149 if (target.bindingType == BindingType::Element) {
4150 if (target.defaultValue)
4151 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
4152 target.pattern->bindValue(generator, value.get());
4153 }
4154 break;
4155 }
4156
4157 case BindingType::RestElement: {
4158 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), nullptr, 0, ArrayWithUndecided);
4159
4160 Ref<Label> iterationDone = generator.newLabel();
4161 if (!done)
4162 done = generator.newTemporary();
4163 else
4164 generator.emitJumpIfTrue(done.get(), iterationDone.get());
4165
4166 RefPtr<RegisterID> index = generator.newTemporary();
4167 generator.emitLoad(index.get(), jsNumber(0));
4168 Ref<Label> loopStart = generator.newLabel();
4169 generator.emitLabel(loopStart.get());
4170
4171 RefPtr<RegisterID> value = generator.newTemporary();
4172 generator.emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), this);
4173 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
4174 generator.emitJumpIfTrue(done.get(), iterationDone.get());
4175 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
4176
4177 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
4178 generator.emitInc(index.get());
4179 generator.emitJump(loopStart.get());
4180
4181 generator.emitLabel(iterationDone.get());
4182 target.pattern->bindValue(generator, array.get());
4183 break;
4184 }
4185 }
4186 }
4187
4188 Ref<Label> iteratorClosed = generator.newLabel();
4189 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
4190 generator.emitIteratorClose(iterator.get(), this);
4191 generator.emitLabel(iteratorClosed.get());
4192}
4193
4194RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
4195{
4196 if (!rhs->isSimpleArray())
4197 return nullptr;
4198
4199 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
4200 Vector<ExpressionNode*> elements;
4201 for (; elementNodes; elementNodes = elementNodes->next()) {
4202 ExpressionNode* value = elementNodes->value();
4203 if (value->isSpreadExpression())
4204 return nullptr;
4205 elements.append(value);
4206 }
4207
4208 RefPtr<RegisterID> resultRegister;
4209 if (dst != generator.ignoredResult())
4210 resultRegister = generator.emitNewArray(generator.newTemporary(), nullptr, 0, ArrayWithUndecided);
4211 if (m_targetPatterns.size() != elements.size())
4212 return nullptr;
4213 Vector<RefPtr<RegisterID>> registers;
4214 registers.reserveCapacity(m_targetPatterns.size());
4215 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4216 registers.uncheckedAppend(generator.newTemporary());
4217 generator.emitNode(registers.last().get(), elements[i]);
4218 if (m_targetPatterns[i].defaultValue)
4219 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
4220 if (resultRegister) {
4221 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(i));
4222 generator.emitDirectPutByVal(resultRegister.get(), index.get(), registers.last().get());
4223 }
4224 }
4225
4226 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4227 if (m_targetPatterns[i].pattern)
4228 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
4229 }
4230 if (resultRegister)
4231 return generator.move(generator.finalDestination(dst, resultRegister.get()), resultRegister.get());
4232 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
4233}
4234
4235void ArrayPatternNode::toString(StringBuilder& builder) const
4236{
4237 builder.append('[');
4238 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4239 const auto& target = m_targetPatterns[i];
4240
4241 switch (target.bindingType) {
4242 case BindingType::Elision:
4243 builder.append(',');
4244 break;
4245
4246 case BindingType::Element:
4247 target.pattern->toString(builder);
4248 if (i < m_targetPatterns.size() - 1)
4249 builder.append(',');
4250 break;
4251
4252 case BindingType::RestElement:
4253 builder.appendLiteral("...");
4254 target.pattern->toString(builder);
4255 break;
4256 }
4257 }
4258 builder.append(']');
4259}
4260
4261void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4262{
4263 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4264 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
4265 node->collectBoundIdentifiers(identifiers);
4266 }
4267}
4268
4269void ObjectPatternNode::toString(StringBuilder& builder) const
4270{
4271 builder.append('{');
4272 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4273 if (m_targetPatterns[i].wasString)
4274 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
4275 else
4276 builder.append(m_targetPatterns[i].propertyName.string());
4277 builder.append(':');
4278 m_targetPatterns[i].pattern->toString(builder);
4279 if (i < m_targetPatterns.size() - 1)
4280 builder.append(',');
4281 }
4282 builder.append('}');
4283}
4284
4285void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
4286{
4287 generator.emitRequireObjectCoercible(rhs, "Right side of assignment cannot be destructured"_s);
4288
4289 RefPtr<RegisterID> excludedList;
4290 IdentifierSet excludedSet;
4291 RefPtr<RegisterID> addMethod;
4292 if (m_containsRestElement && m_containsComputedProperty) {
4293 auto var = generator.variable(generator.propertyNames().builtinNames().SetPrivateName());
4294
4295 RefPtr<RegisterID> scope = generator.newTemporary();
4296 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
4297 RefPtr<RegisterID> setConstructor = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4298
4299 CallArguments args(generator, nullptr, 0);
4300 excludedList = generator.emitConstruct(generator.newTemporary(), setConstructor.get(), setConstructor.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
4301
4302 addMethod = generator.emitGetById(generator.newTemporary(), excludedList.get(), generator.propertyNames().builtinNames().addPrivateName());
4303 }
4304
4305 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4306 const auto& target = m_targetPatterns[i];
4307 if (target.bindingType == BindingType::Element) {
4308 RefPtr<RegisterID> temp = generator.newTemporary();
4309 RefPtr<RegisterID> propertyName;
4310 if (!target.propertyExpression) {
4311 Optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
4312 if (!optionalIndex)
4313 generator.emitGetById(temp.get(), rhs, target.propertyName);
4314 else {
4315 RefPtr<RegisterID> propertyIndex = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
4316 generator.emitGetByVal(temp.get(), rhs, propertyIndex.get());
4317 }
4318 } else {
4319 propertyName = generator.emitNodeForProperty(target.propertyExpression);
4320 generator.emitGetByVal(temp.get(), rhs, propertyName.get());
4321 }
4322
4323 if (m_containsRestElement) {
4324 if (m_containsComputedProperty) {
4325 if (!target.propertyExpression)
4326 propertyName = generator.emitLoad(nullptr, target.propertyName);
4327
4328 CallArguments args(generator, nullptr, 1);
4329 generator.move(args.thisRegister(), excludedList.get());
4330 generator.move(args.argumentRegister(0), propertyName.get());
4331 generator.emitCall(generator.newTemporary(), addMethod.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4332 } else
4333 excludedSet.add(target.propertyName.impl());
4334 }
4335
4336 if (target.defaultValue)
4337 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
4338 target.pattern->bindValue(generator, temp.get());
4339 } else {
4340 ASSERT(target.bindingType == BindingType::RestElement);
4341 ASSERT(i == m_targetPatterns.size() - 1);
4342 RefPtr<RegisterID> newObject = generator.emitNewObject(generator.newTemporary());
4343
4344 // load and call @copyDataProperties
4345 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
4346
4347 RefPtr<RegisterID> scope = generator.newTemporary();
4348 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
4349 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4350
4351 CallArguments args(generator, nullptr, 3);
4352 generator.emitLoad(args.thisRegister(), jsUndefined());
4353 generator.move(args.argumentRegister(0), newObject.get());
4354 generator.move(args.argumentRegister(1), rhs);
4355 if (m_containsComputedProperty)
4356 generator.move(args.argumentRegister(2), excludedList.get());
4357 else {
4358 RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
4359 generator.move(args.argumentRegister(2), excludedSetReg.get());
4360 }
4361
4362 RefPtr<RegisterID> result = generator.newTemporary();
4363 generator.emitCall(result.get(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4364 target.pattern->bindValue(generator, result.get());
4365 }
4366 }
4367}
4368
4369void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4370{
4371 for (size_t i = 0; i < m_targetPatterns.size(); i++)
4372 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
4373}
4374
4375void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
4376{
4377 Variable var = generator.variable(m_boundProperty);
4378 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
4379 if (RegisterID* local = var.local()) {
4380 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4381 generator.emitTDZCheckIfNecessary(var, local, nullptr);
4382 if (isReadOnly) {
4383 generator.emitReadOnlyExceptionIfNeeded(var);
4384 return;
4385 }
4386 generator.move(local, value);
4387 generator.emitProfileType(local, var, divotStart(), divotEnd());
4388 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
4389 generator.liftTDZCheckIfPossible(var);
4390 return;
4391 }
4392 if (generator.isStrictMode())
4393 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4394 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
4395 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4396 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4397 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
4398 if (isReadOnly) {
4399 generator.emitReadOnlyExceptionIfNeeded(var);
4400 return;
4401 }
4402 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
4403 generator.emitProfileType(value, var, divotStart(), divotEnd());
4404 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
4405 generator.liftTDZCheckIfPossible(var);
4406 return;
4407}
4408
4409void BindingNode::toString(StringBuilder& builder) const
4410{
4411 builder.append(m_boundProperty.string());
4412}
4413
4414void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4415{
4416 identifiers.append(m_boundProperty);
4417}
4418
4419void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
4420{
4421}
4422
4423void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
4424{
4425 if (m_assignmentTarget->isResolveNode()) {
4426 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
4427 Variable var = generator.variable(lhs->identifier());
4428 bool isReadOnly = var.isReadOnly();
4429 if (RegisterID* local = var.local()) {
4430 generator.emitTDZCheckIfNecessary(var, local, nullptr);
4431
4432 if (isReadOnly)
4433 generator.emitReadOnlyExceptionIfNeeded(var);
4434 else {
4435 generator.move(local, value);
4436 generator.emitProfileType(local, divotStart(), divotEnd());
4437 }
4438 return;
4439 }
4440 if (generator.isStrictMode())
4441 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4442 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
4443 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
4444 if (isReadOnly) {
4445 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
4446 if (threwException)
4447 return;
4448 }
4449 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4450 if (!isReadOnly) {
4451 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
4452 generator.emitProfileType(value, var, divotStart(), divotEnd());
4453 }
4454 } else if (m_assignmentTarget->isDotAccessorNode()) {
4455 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
4456 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4457 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4458 if (lhs->base()->isSuperNode()) {
4459 RefPtr<RegisterID> thisValue = generator.ensureThis();
4460 generator.emitPutById(base.get(), thisValue.get(), lhs->identifier(), value);
4461 } else
4462 generator.emitPutById(base.get(), lhs->identifier(), value);
4463 generator.emitProfileType(value, divotStart(), divotEnd());
4464 } else if (m_assignmentTarget->isBracketAccessorNode()) {
4465 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
4466 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4467 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(lhs->subscript(), true, false);
4468 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4469 if (lhs->base()->isSuperNode()) {
4470 RefPtr<RegisterID> thisValue = generator.ensureThis();
4471 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
4472 } else
4473 generator.emitPutByVal(base.get(), property.get(), value);
4474 generator.emitProfileType(value, divotStart(), divotEnd());
4475 }
4476}
4477
4478void AssignmentElementNode::toString(StringBuilder& builder) const
4479{
4480 if (m_assignmentTarget->isResolveNode())
4481 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
4482}
4483
4484void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4485{
4486 m_pattern->collectBoundIdentifiers(identifiers);
4487}
4488
4489void RestParameterNode::toString(StringBuilder& builder) const
4490{
4491 builder.appendLiteral("...");
4492 m_pattern->toString(builder);
4493}
4494
4495void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
4496{
4497 RELEASE_ASSERT_NOT_REACHED();
4498}
4499
4500void RestParameterNode::emit(BytecodeGenerator& generator)
4501{
4502 RefPtr<RegisterID> temp = generator.newTemporary();
4503 generator.emitRestParameter(temp.get(), m_numParametersToSkip);
4504 m_pattern->bindValue(generator, temp.get());
4505}
4506
4507
4508RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4509{
4510 RELEASE_ASSERT_NOT_REACHED();
4511 return 0;
4512}
4513
4514RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4515{
4516 RefPtr<RegisterID> src = generator.newTemporary();
4517 generator.emitNode(src.get(), m_expression);
4518
4519 // load and call @copyDataPropertiesNoExclusions
4520 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesNoExclusionsPrivateName());
4521
4522 RefPtr<RegisterID> scope = generator.newTemporary();
4523 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
4524 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4525
4526 CallArguments args(generator, nullptr, 2);
4527 generator.emitLoad(args.thisRegister(), jsUndefined());
4528 generator.move(args.argumentRegister(0), dst);
4529 generator.move(args.argumentRegister(1), src.get());
4530
4531 generator.emitCall(generator.newTemporary(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4532
4533 return dst;
4534}
4535
4536} // namespace JSC
4537