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 ASSERT(m_expr->isFunctionCall());
1670 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
1671 ? "Postfix ++ operator applied to value that is not a reference."_s
1672 : "Postfix -- operator applied to value that is not a reference."_s);
1673}
1674
1675// ------------------------------ DeleteResolveNode -----------------------------------
1676
1677RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1678{
1679 Variable var = generator.variable(m_ident);
1680 if (var.local()) {
1681 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
1682 return generator.emitLoad(generator.finalDestination(dst), false);
1683 }
1684
1685 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1686 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
1687 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
1688 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
1689}
1690
1691// ------------------------------ DeleteBracketNode -----------------------------------
1692
1693RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1694{
1695 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
1696 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
1697
1698 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1699 if (m_base->isSuperNode())
1700 return emitThrowReferenceError(generator, "Cannot delete a super property");
1701 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
1702}
1703
1704// ------------------------------ DeleteDotNode -----------------------------------
1705
1706RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1707{
1708 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
1709
1710 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1711 if (m_base->isSuperNode())
1712 return emitThrowReferenceError(generator, "Cannot delete a super property");
1713 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
1714}
1715
1716// ------------------------------ DeleteValueNode -----------------------------------
1717
1718RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1719{
1720 generator.emitNode(generator.ignoredResult(), m_expr);
1721
1722 // delete on a non-location expression ignores the value and returns true
1723 return generator.emitLoad(generator.finalDestination(dst), true);
1724}
1725
1726// ------------------------------ VoidNode -------------------------------------
1727
1728RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1729{
1730 if (dst == generator.ignoredResult()) {
1731 generator.emitNode(generator.ignoredResult(), m_expr);
1732 return 0;
1733 }
1734 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1735 return generator.emitLoad(dst, jsUndefined());
1736}
1737
1738// ------------------------------ TypeOfResolveNode -----------------------------------
1739
1740RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1741{
1742 Variable var = generator.variable(m_ident);
1743 if (RegisterID* local = var.local()) {
1744 generator.emitTDZCheckIfNecessary(var, local, nullptr);
1745 if (dst == generator.ignoredResult())
1746 return 0;
1747 return generator.emitTypeOf(generator.finalDestination(dst), local);
1748 }
1749
1750 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1751 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
1752 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
1753 if (dst == generator.ignoredResult())
1754 return 0;
1755 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
1756}
1757
1758// ------------------------------ TypeOfValueNode -----------------------------------
1759
1760RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1761{
1762 if (dst == generator.ignoredResult()) {
1763 generator.emitNode(generator.ignoredResult(), m_expr);
1764 return 0;
1765 }
1766 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1767 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1768}
1769
1770// ------------------------------ PrefixNode ----------------------------------
1771
1772RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
1773{
1774 ASSERT(m_expr->isResolveNode());
1775 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1776 const Identifier& ident = resolve->identifier();
1777
1778 Variable var = generator.variable(ident);
1779 if (RegisterID* local = var.local()) {
1780 generator.emitTDZCheckIfNecessary(var, local, nullptr);
1781 RefPtr<RegisterID> localReg = local;
1782 if (var.isReadOnly()) {
1783 generator.emitReadOnlyExceptionIfNeeded(var);
1784 localReg = generator.move(generator.tempDestination(dst), localReg.get());
1785 } else if (generator.shouldEmitTypeProfilerHooks()) {
1786 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1787 generator.move(tempDst.get(), localReg.get());
1788 emitIncOrDec(generator, tempDst.get(), m_operator);
1789 generator.move(localReg.get(), tempDst.get());
1790 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1791 return generator.move(dst, tempDst.get());
1792 }
1793 emitIncOrDec(generator, localReg.get(), m_operator);
1794 return generator.move(dst, localReg.get());
1795 }
1796
1797 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1798 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1799 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
1800 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
1801 if (var.isReadOnly()) {
1802 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1803 if (threwException)
1804 return value.get();
1805 }
1806
1807 emitIncOrDec(generator, value.get(), m_operator);
1808 if (!var.isReadOnly()) {
1809 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
1810 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1811 }
1812 return generator.move(dst, value.get());
1813}
1814
1815RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
1816{
1817 ASSERT(m_expr->isBracketAccessorNode());
1818 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1819 ExpressionNode* baseNode = bracketAccessor->base();
1820 ExpressionNode* subscript = bracketAccessor->subscript();
1821
1822 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
1823 RefPtr<RegisterID> property = generator.emitNodeForProperty(subscript);
1824 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1825
1826 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
1827 RegisterID* value;
1828 RefPtr<RegisterID> thisValue;
1829 if (baseNode->isSuperNode()) {
1830 thisValue = generator.ensureThis();
1831 value = generator.emitGetByVal(propDst.get(), base.get(), thisValue.get(), property.get());
1832 } else
1833 value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
1834 emitIncOrDec(generator, value, m_operator);
1835 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1836 if (baseNode->isSuperNode())
1837 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
1838 else
1839 generator.emitPutByVal(base.get(), property.get(), value);
1840 generator.emitProfileType(value, divotStart(), divotEnd());
1841 return generator.move(dst, propDst.get());
1842}
1843
1844RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
1845{
1846 ASSERT(m_expr->isDotAccessorNode());
1847 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1848 ExpressionNode* baseNode = dotAccessor->base();
1849 const Identifier& ident = dotAccessor->identifier();
1850
1851 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1852 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1853
1854 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
1855 RegisterID* value;
1856 RefPtr<RegisterID> thisValue;
1857 if (baseNode->isSuperNode()) {
1858 thisValue = generator.ensureThis();
1859 value = generator.emitGetById(propDst.get(), base.get(), thisValue.get(), ident);
1860 } else
1861 value = generator.emitGetById(propDst.get(), base.get(), ident);
1862 emitIncOrDec(generator, value, m_operator);
1863 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1864 if (baseNode->isSuperNode())
1865 generator.emitPutById(base.get(), thisValue.get(), ident, value);
1866 else
1867 generator.emitPutById(base.get(), ident, value);
1868 generator.emitProfileType(value, divotStart(), divotEnd());
1869 return generator.move(dst, propDst.get());
1870}
1871
1872RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1873{
1874 if (m_expr->isResolveNode())
1875 return emitResolve(generator, dst);
1876
1877 if (m_expr->isBracketAccessorNode())
1878 return emitBracket(generator, dst);
1879
1880 if (m_expr->isDotAccessorNode())
1881 return emitDot(generator, dst);
1882
1883 ASSERT(m_expr->isFunctionCall());
1884 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
1885 ? "Prefix ++ operator applied to value that is not a reference."_s
1886 : "Prefix -- operator applied to value that is not a reference."_s);
1887}
1888
1889// ------------------------------ Unary Operation Nodes -----------------------------------
1890
1891RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1892{
1893 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1894 generator.emitExpressionInfo(position(), position(), position());
1895 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor()));
1896}
1897
1898// ------------------------------ UnaryPlusNode -----------------------------------
1899
1900RegisterID* UnaryPlusNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1901{
1902 ASSERT(opcodeID() == op_to_number);
1903 RefPtr<RegisterID> src = generator.emitNode(expr());
1904 generator.emitExpressionInfo(position(), position(), position());
1905 return generator.emitToNumber(generator.finalDestination(dst), src.get());
1906}
1907
1908// ------------------------------ LogicalNotNode -----------------------------------
1909
1910void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
1911{
1912 if (UNLIKELY(needsDebugHook()))
1913 generator.emitDebugHook(this);
1914
1915 // Reverse the true and false targets.
1916 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
1917}
1918
1919
1920// ------------------------------ Binary Operation Nodes -----------------------------------
1921
1922// BinaryOpNode::emitStrcat:
1923//
1924// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1925// more values, where we can determine a set of separate op_add operations would be operating on
1926// string values.
1927//
1928// This function expects to be operating on a graph of AST nodes looking something like this:
1929//
1930// (a)... (b)
1931// \ /
1932// (+) (c)
1933// \ /
1934// [d] ((+))
1935// \ /
1936// [+=]
1937//
1938// The assignment operation is optional, if it exists the register holding the value on the
1939// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1940//
1941// The method should be called on the node at the root of the tree of regular binary add
1942// operations (marked in the diagram with a double set of parentheses). This node must
1943// be performing a string concatenation (determined by statically detecting that at least
1944// one child must be a string).
1945//
1946// Since the minimum number of values being concatenated together is expected to be 3, if
1947// a lhs to a concatenating assignment is not provided then the root add should have at
1948// least one left child that is also an add that can be determined to be operating on strings.
1949//
1950RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1951{
1952 ASSERT(isAdd());
1953 ASSERT(resultDescriptor().definitelyIsString());
1954
1955 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1956 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1957 // added first, and the leftmost child is never added, so the vector produced for the
1958 // example above will be [ c, b ].
1959 Vector<ExpressionNode*, 16> reverseExpressionList;
1960 reverseExpressionList.append(m_expr2);
1961
1962 // Examine the left child of the add. So long as this is a string add, add its right-child
1963 // to the list, and keep processing along the left fork.
1964 ExpressionNode* leftMostAddChild = m_expr1;
1965 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1966 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1967 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1968 }
1969
1970 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1971
1972 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1973 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1974 // op_strcat node handle its conversion if required).
1975 if (lhs)
1976 temporaryRegisters.append(generator.newTemporary());
1977
1978 // Emit code for the leftmost node ((a) in the example).
1979 temporaryRegisters.append(generator.newTemporary());
1980 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1981 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1982
1983 // Note on ordering of conversions:
1984 //
1985 // We maintain the same ordering of conversions as we would see if the concatenations
1986 // was performed as a sequence of adds (otherwise this optimization could change
1987 // behaviour should an object have been provided a valueOf or toString method).
1988 //
1989 // Considering the above example, the sequnce of execution is:
1990 // * evaluate operand (a)
1991 // * evaluate operand (b)
1992 // * convert (a) to primitive <- (this would be triggered by the first add)
1993 // * convert (b) to primitive <- (ditto)
1994 // * evaluate operand (c)
1995 // * convert (c) to primitive <- (this would be triggered by the second add)
1996 // And optionally, if there is an assignment:
1997 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1998 //
1999 // As such we do not plant an op to convert the leftmost child now. Instead, use
2000 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
2001 // once the second node has been generated. However, if the leftmost child is an
2002 // immediate we can trivially determine that no conversion will be required.
2003 // If this is the case
2004 if (leftMostAddChild->isString())
2005 leftMostAddChildTempRegister = 0;
2006
2007 while (reverseExpressionList.size()) {
2008 ExpressionNode* node = reverseExpressionList.last();
2009 reverseExpressionList.removeLast();
2010
2011 // Emit the code for the current node.
2012 temporaryRegisters.append(generator.newTemporary());
2013 generator.emitNode(temporaryRegisters.last().get(), node);
2014
2015 // On the first iteration of this loop, when we first reach this point we have just
2016 // generated the second node, which means it is time to convert the leftmost operand.
2017 if (leftMostAddChildTempRegister) {
2018 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
2019 leftMostAddChildTempRegister = 0; // Only do this once.
2020 }
2021 // Plant a conversion for this node, if necessary.
2022 if (!node->isString())
2023 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
2024 }
2025 ASSERT(temporaryRegisters.size() >= 3);
2026
2027 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2028 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2029 if (emitExpressionInfoForMe)
2030 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
2031 // If there is an assignment convert the lhs now. This will also copy lhs to
2032 // the temporary register we allocated for it.
2033 if (lhs)
2034 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
2035
2036 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
2037}
2038
2039void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
2040{
2041 TriState branchCondition;
2042 ExpressionNode* branchExpression;
2043 tryFoldToBranch(generator, branchCondition, branchExpression);
2044
2045 if (UNLIKELY(needsDebugHook())) {
2046 if (branchCondition != MixedTriState)
2047 generator.emitDebugHook(this);
2048 }
2049
2050 if (branchCondition == MixedTriState)
2051 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
2052 else if (branchCondition == TrueTriState)
2053 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
2054 else
2055 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
2056}
2057
2058static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
2059{
2060 ResultType expressionType = branchExpression->resultDescriptor();
2061
2062 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
2063 return true;
2064 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
2065 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
2066 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
2067 return true;
2068
2069 return false;
2070}
2071
2072void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
2073{
2074 branchCondition = MixedTriState;
2075 branchExpression = 0;
2076
2077 ConstantNode* constant = 0;
2078 if (m_expr1->isConstant()) {
2079 constant = static_cast<ConstantNode*>(m_expr1);
2080 branchExpression = m_expr2;
2081 } else if (m_expr2->isConstant()) {
2082 constant = static_cast<ConstantNode*>(m_expr2);
2083 branchExpression = m_expr1;
2084 }
2085
2086 if (!constant)
2087 return;
2088 ASSERT(branchExpression);
2089
2090 OpcodeID opcodeID = this->opcodeID();
2091 JSValue value = constant->jsValue(generator);
2092 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
2093 if (!canFoldToBranch)
2094 return;
2095
2096 if (opcodeID == op_eq || opcodeID == op_stricteq)
2097 branchCondition = triState(value.pureToBoolean());
2098 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
2099 branchCondition = triState(!value.pureToBoolean());
2100}
2101
2102RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2103{
2104 OpcodeID opcodeID = this->opcodeID();
2105
2106 if (opcodeID == op_less || opcodeID == op_lesseq || opcodeID == op_greater || opcodeID == op_greatereq) {
2107 auto isUInt32 = [&] (ExpressionNode* node) -> Optional<UInt32Result> {
2108 if (node->isBinaryOpNode() && static_cast<BinaryOpNode*>(node)->opcodeID() == op_urshift)
2109 return UInt32Result::UInt32;
2110 if (node->isNumber() && static_cast<NumberNode*>(node)->isIntegerNode()) {
2111 auto value = jsNumber(static_cast<NumberNode*>(node)->value());
2112 if (value.isInt32() && value.asInt32() >= 0)
2113 return UInt32Result::Constant;
2114 }
2115 return WTF::nullopt;
2116 };
2117 auto leftResult = isUInt32(m_expr1);
2118 auto rightResult = isUInt32(m_expr2);
2119 if ((leftResult && rightResult) && (leftResult.value() == UInt32Result::UInt32 || rightResult.value() == UInt32Result::UInt32)) {
2120 auto* left = m_expr1;
2121 auto* right = m_expr2;
2122 if (left->isBinaryOpNode()) {
2123 ASSERT(static_cast<BinaryOpNode*>(left)->opcodeID() == op_urshift);
2124 static_cast<BinaryOpNode*>(left)->m_shouldToUnsignedResult = false;
2125 }
2126 if (right->isBinaryOpNode()) {
2127 ASSERT(static_cast<BinaryOpNode*>(right)->opcodeID() == op_urshift);
2128 static_cast<BinaryOpNode*>(right)->m_shouldToUnsignedResult = false;
2129 }
2130 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
2131 RefPtr<RegisterID> src2 = generator.emitNode(right);
2132 generator.emitExpressionInfo(position(), position(), position());
2133
2134 // Since the both sides only accept Int32, replacing operands is not observable to users.
2135 bool replaceOperands = false;
2136 OpcodeID resultOp = opcodeID;
2137 switch (opcodeID) {
2138 case op_less:
2139 resultOp = op_below;
2140 break;
2141 case op_lesseq:
2142 resultOp = op_beloweq;
2143 break;
2144 case op_greater:
2145 resultOp = op_below;
2146 replaceOperands = true;
2147 break;
2148 case op_greatereq:
2149 resultOp = op_beloweq;
2150 replaceOperands = true;
2151 break;
2152 default:
2153 RELEASE_ASSERT_NOT_REACHED();
2154 }
2155 OperandTypes operandTypes(left->resultDescriptor(), right->resultDescriptor());
2156 if (replaceOperands) {
2157 std::swap(src1, src2);
2158 operandTypes = OperandTypes(right->resultDescriptor(), left->resultDescriptor());
2159 }
2160 return generator.emitBinaryOp(resultOp, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), operandTypes);
2161 }
2162 }
2163
2164 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
2165 generator.emitExpressionInfo(position(), position(), position());
2166 return emitStrcat(generator, dst);
2167 }
2168
2169 if (opcodeID == op_neq) {
2170 if (m_expr1->isNull() || m_expr2->isNull()) {
2171 RefPtr<RegisterID> src = generator.tempDestination(dst);
2172 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
2173 return generator.emitUnaryOp<OpNeqNull>(generator.finalDestination(dst, src.get()), src.get());
2174 }
2175 }
2176
2177 ExpressionNode* left = m_expr1;
2178 ExpressionNode* right = m_expr2;
2179 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
2180 if (left->isString())
2181 std::swap(left, right);
2182 }
2183
2184 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
2185 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
2186 RefPtr<RegisterID> src2 = generator.emitNode(right);
2187 generator.emitExpressionInfo(position(), position(), position());
2188 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
2189 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
2190 if (opcodeID == op_neq)
2191 generator.emitEqualityOp<OpEq>(generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
2192 else if (opcodeID == op_nstricteq)
2193 generator.emitEqualityOp<OpStricteq>(generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
2194 else
2195 RELEASE_ASSERT_NOT_REACHED();
2196 return generator.emitUnaryOp<OpNot>(generator.finalDestination(dst, tmp.get()), tmp.get());
2197 }
2198 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
2199 if (m_shouldToUnsignedResult) {
2200 if (opcodeID == op_urshift && dst != generator.ignoredResult())
2201 return generator.emitUnaryOp<OpUnsigned>(result, result);
2202 }
2203 return result;
2204}
2205
2206RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2207{
2208 if (m_expr1->isNull() || m_expr2->isNull()) {
2209 RefPtr<RegisterID> src = generator.tempDestination(dst);
2210 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
2211 return generator.emitUnaryOp<OpEqNull>(generator.finalDestination(dst, src.get()), src.get());
2212 }
2213
2214 ExpressionNode* left = m_expr1;
2215 ExpressionNode* right = m_expr2;
2216 if (left->isString())
2217 std::swap(left, right);
2218
2219 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
2220 RefPtr<RegisterID> src2 = generator.emitNode(right);
2221 return generator.emitEqualityOp<OpEq>(generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
2222}
2223
2224RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2225{
2226 ExpressionNode* left = m_expr1;
2227 ExpressionNode* right = m_expr2;
2228 if (left->isString())
2229 std::swap(left, right);
2230
2231 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
2232 RefPtr<RegisterID> src2 = generator.emitNode(right);
2233 return generator.emitEqualityOp<OpStricteq>(generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
2234}
2235
2236RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2237{
2238 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2239 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
2240 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2241 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
2242}
2243
2244RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2245{
2246 RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
2247 RefPtr<RegisterID> isObject = generator.newTemporary();
2248 RefPtr<RegisterID> isCustom = generator.newTemporary();
2249 RefPtr<RegisterID> prototype = generator.newTemporary();
2250 RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2251 RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
2252 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
2253 Ref<Label> custom = generator.newLabel();
2254 Ref<Label> done = generator.newLabel();
2255 Ref<Label> typeError = generator.newLabel();
2256
2257 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2258 generator.emitIsObject(isObject.get(), constructor.get());
2259 generator.emitJumpIfFalse(isObject.get(), typeError.get());
2260
2261 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2262 generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
2263
2264 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2265 generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
2266
2267 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2268 generator.emitJumpIfTrue(isCustom.get(), custom.get());
2269
2270 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2271 generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
2272
2273 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2274 generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
2275
2276 generator.emitJump(done.get());
2277
2278 generator.emitLabel(typeError.get());
2279 generator.emitThrowTypeError("Right hand side of instanceof is not an object");
2280
2281 generator.emitLabel(custom.get());
2282
2283 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2284 generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
2285
2286 generator.emitLabel(done.get());
2287
2288 return dstReg.get();
2289}
2290
2291// ------------------------------ InNode ----------------------------
2292
2293RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2294{
2295 if (isNonIndexStringElement(*m_expr1)) {
2296 RefPtr<RegisterID> base = generator.emitNode(m_expr2);
2297 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2298 return generator.emitInById(generator.finalDestination(dst, base.get()), base.get(), static_cast<StringNode*>(m_expr1)->value());
2299 }
2300
2301 RefPtr<RegisterID> key = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2302 RefPtr<RegisterID> base = generator.emitNode(m_expr2);
2303 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2304 return generator.emitInByVal(generator.finalDestination(dst, key.get()), key.get(), base.get());
2305}
2306
2307
2308// ------------------------------ LogicalOpNode ----------------------------
2309
2310RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2311{
2312 RefPtr<RegisterID> temp = generator.tempDestination(dst);
2313 Ref<Label> target = generator.newLabel();
2314
2315 generator.emitNode(temp.get(), m_expr1);
2316 if (m_operator == OpLogicalAnd)
2317 generator.emitJumpIfFalse(temp.get(), target.get());
2318 else
2319 generator.emitJumpIfTrue(temp.get(), target.get());
2320 generator.emitNodeInTailPosition(temp.get(), m_expr2);
2321 generator.emitLabel(target.get());
2322
2323 return generator.move(dst, temp.get());
2324}
2325
2326void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
2327{
2328 if (UNLIKELY(needsDebugHook()))
2329 generator.emitDebugHook(this);
2330
2331 Ref<Label> afterExpr1 = generator.newLabel();
2332 if (m_operator == OpLogicalAnd)
2333 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
2334 else
2335 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
2336 generator.emitLabel(afterExpr1.get());
2337
2338 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
2339}
2340
2341// ------------------------------ ConditionalNode ------------------------------
2342
2343RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2344{
2345 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
2346 Ref<Label> beforeElse = generator.newLabel();
2347 Ref<Label> afterElse = generator.newLabel();
2348
2349 Ref<Label> beforeThen = generator.newLabel();
2350 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
2351 generator.emitLabel(beforeThen.get());
2352
2353 generator.emitProfileControlFlow(m_expr1->startOffset());
2354 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
2355 generator.emitJump(afterElse.get());
2356
2357 generator.emitLabel(beforeElse.get());
2358 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
2359 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
2360
2361 generator.emitLabel(afterElse.get());
2362
2363 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
2364
2365 return newDst.get();
2366}
2367
2368// ------------------------------ ReadModifyResolveNode -----------------------------------
2369
2370// FIXME: should this be moved to be a method on BytecodeGenerator?
2371static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
2372{
2373 OpcodeID opcodeID;
2374 switch (oper) {
2375 case OpMultEq:
2376 opcodeID = op_mul;
2377 break;
2378 case OpDivEq:
2379 opcodeID = op_div;
2380 break;
2381 case OpPlusEq:
2382 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
2383 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
2384 opcodeID = op_add;
2385 break;
2386 case OpMinusEq:
2387 opcodeID = op_sub;
2388 break;
2389 case OpLShift:
2390 opcodeID = op_lshift;
2391 break;
2392 case OpRShift:
2393 opcodeID = op_rshift;
2394 break;
2395 case OpURShift:
2396 opcodeID = op_urshift;
2397 break;
2398 case OpAndEq:
2399 opcodeID = op_bitand;
2400 break;
2401 case OpXOrEq:
2402 opcodeID = op_bitxor;
2403 break;
2404 case OpOrEq:
2405 opcodeID = op_bitor;
2406 break;
2407 case OpModEq:
2408 opcodeID = op_mod;
2409 break;
2410 case OpPowEq:
2411 opcodeID = op_pow;
2412 break;
2413 default:
2414 RELEASE_ASSERT_NOT_REACHED();
2415 return dst;
2416 }
2417
2418 RegisterID* src2 = generator.emitNode(m_right);
2419
2420 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2421 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2422 if (emitExpressionInfoForMe)
2423 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
2424 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
2425 if (oper == OpURShift)
2426 return generator.emitUnaryOp<OpUnsigned>(result, result);
2427 return result;
2428}
2429
2430RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2431{
2432 JSTextPosition newDivot = divotStart() + m_ident.length();
2433 Variable var = generator.variable(m_ident);
2434 if (RegisterID* local = var.local()) {
2435 generator.emitTDZCheckIfNecessary(var, local, nullptr);
2436 if (var.isReadOnly()) {
2437 generator.emitReadOnlyExceptionIfNeeded(var);
2438 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2439 generator.emitProfileType(result, divotStart(), divotEnd());
2440 return result;
2441 }
2442
2443 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
2444 RefPtr<RegisterID> result = generator.newTemporary();
2445 generator.move(result.get(), local);
2446 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2447 generator.move(local, result.get());
2448 generator.emitProfileType(local, divotStart(), divotEnd());
2449 return generator.move(dst, result.get());
2450 }
2451
2452 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2453 generator.emitProfileType(result, divotStart(), divotEnd());
2454 return generator.move(dst, result);
2455 }
2456
2457 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
2458 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2459 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
2460 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
2461 if (var.isReadOnly()) {
2462 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2463 if (threwException)
2464 return value.get();
2465 }
2466 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
2467 RegisterID* returnResult = result.get();
2468 if (!var.isReadOnly()) {
2469 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
2470 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2471 }
2472 return returnResult;
2473}
2474
2475static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
2476{
2477 switch (assignmentContext) {
2478 case AssignmentContext::DeclarationStatement:
2479 return InitializationMode::Initialization;
2480 case AssignmentContext::ConstDeclarationStatement:
2481 return InitializationMode::ConstInitialization;
2482 case AssignmentContext::AssignmentExpression:
2483 return InitializationMode::NotInitialization;
2484 }
2485
2486 ASSERT_NOT_REACHED();
2487 return InitializationMode::NotInitialization;
2488}
2489
2490// ------------------------------ AssignResolveNode -----------------------------------
2491
2492RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2493{
2494 Variable var = generator.variable(m_ident);
2495 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
2496 if (RegisterID* local = var.local()) {
2497 RegisterID* result = nullptr;
2498 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2499 generator.emitTDZCheckIfNecessary(var, local, nullptr);
2500
2501 if (isReadOnly) {
2502 result = generator.emitNode(dst, m_right); // Execute side effects first.
2503 generator.emitReadOnlyExceptionIfNeeded(var);
2504 generator.emitProfileType(result, var, divotStart(), divotEnd());
2505 } else if (var.isSpecial()) {
2506 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
2507 generator.emitNode(tempDst.get(), m_right);
2508 generator.move(local, tempDst.get());
2509 generator.emitProfileType(local, var, divotStart(), divotEnd());
2510 result = generator.move(dst, tempDst.get());
2511 } else {
2512 RegisterID* right = generator.emitNode(local, m_right);
2513 generator.emitProfileType(right, var, divotStart(), divotEnd());
2514 result = generator.move(dst, right);
2515 }
2516
2517 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
2518 generator.liftTDZCheckIfPossible(var);
2519 return result;
2520 }
2521
2522 if (generator.isStrictMode())
2523 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2524 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2525 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2526 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
2527 if (dst == generator.ignoredResult())
2528 dst = 0;
2529 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
2530 if (isReadOnly) {
2531 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
2532 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2533 if (threwException)
2534 return result;
2535 }
2536 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2537 RegisterID* returnResult = result.get();
2538 if (!isReadOnly) {
2539 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
2540 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2541 }
2542
2543 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
2544 generator.liftTDZCheckIfPossible(var);
2545 return returnResult;
2546}
2547
2548// ------------------------------ AssignDotNode -----------------------------------
2549
2550RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2551{
2552 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2553 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
2554 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
2555 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2556 RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.move(generator.tempDestination(result.get()), result.get());
2557 if (m_base->isSuperNode()) {
2558 RefPtr<RegisterID> thisValue = generator.ensureThis();
2559 generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
2560 } else
2561 generator.emitPutById(base.get(), m_ident, forwardResult.get());
2562 generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
2563 return generator.move(dst, forwardResult.get());
2564}
2565
2566// ------------------------------ ReadModifyDotNode -----------------------------------
2567
2568RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2569{
2570 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2571
2572 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
2573 RefPtr<RegisterID> value;
2574 RefPtr<RegisterID> thisValue;
2575 if (m_base->isSuperNode()) {
2576 thisValue = generator.ensureThis();
2577 value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
2578 } else
2579 value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
2580 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()));
2581
2582 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2583 RegisterID* ret;
2584 if (m_base->isSuperNode())
2585 ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
2586 else
2587 ret = generator.emitPutById(base.get(), m_ident, updatedValue);
2588 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
2589 return ret;
2590}
2591
2592// ------------------------------ AssignErrorNode -----------------------------------
2593
2594RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2595{
2596 return emitThrowReferenceError(generator, "Left side of assignment is not a reference."_s);
2597}
2598
2599// ------------------------------ AssignBracketNode -----------------------------------
2600
2601RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2602{
2603 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2604 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2605 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
2606 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
2607
2608 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2609 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.move(generator.tempDestination(result.get()), result.get());
2610
2611 if (isNonIndexStringElement(*m_subscript)) {
2612 if (m_base->isSuperNode()) {
2613 RefPtr<RegisterID> thisValue = generator.ensureThis();
2614 generator.emitPutById(base.get(), thisValue.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2615 } else
2616 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2617 } else {
2618 if (m_base->isSuperNode()) {
2619 RefPtr<RegisterID> thisValue = generator.ensureThis();
2620 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), forwardResult);
2621 } else
2622 generator.emitPutByVal(base.get(), property.get(), forwardResult);
2623 }
2624
2625 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
2626 return generator.move(dst, forwardResult);
2627}
2628
2629// ------------------------------ ReadModifyBracketNode -----------------------------------
2630
2631RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2632{
2633 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2634 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2635
2636 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
2637 RefPtr<RegisterID> value;
2638 RefPtr<RegisterID> thisValue;
2639 if (m_base->isSuperNode()) {
2640 thisValue = generator.ensureThis();
2641 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisValue.get(), property.get());
2642 } else
2643 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
2644 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()));
2645
2646 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2647 if (m_base->isSuperNode())
2648 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), updatedValue);
2649 else
2650 generator.emitPutByVal(base.get(), property.get(), updatedValue);
2651 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
2652
2653 return updatedValue;
2654}
2655
2656// ------------------------------ CommaNode ------------------------------------
2657
2658RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2659{
2660 CommaNode* node = this;
2661 for (; node && node->next(); node = node->next())
2662 generator.emitNode(generator.ignoredResult(), node->m_expr);
2663 return generator.emitNodeInTailPosition(dst, node->m_expr);
2664}
2665
2666// ------------------------------ SourceElements -------------------------------
2667
2668inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2669{
2670 StatementNode* lastStatementWithCompletionValue = nullptr;
2671 if (generator.shouldBeConcernedWithCompletionValue()) {
2672 for (StatementNode* statement = m_head; statement; statement = statement->next()) {
2673 if (statement->hasCompletionValue())
2674 lastStatementWithCompletionValue = statement;
2675 }
2676 }
2677
2678 for (StatementNode* statement = m_head; statement; statement = statement->next()) {
2679 if (statement == lastStatementWithCompletionValue)
2680 generator.emitLoad(dst, jsUndefined());
2681 generator.emitNodeInTailPosition(dst, statement);
2682 }
2683}
2684
2685// ------------------------------ BlockNode ------------------------------------
2686
2687void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2688{
2689 if (!m_statements)
2690 return;
2691 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
2692 m_statements->emitBytecode(generator, dst);
2693 generator.popLexicalScope(this);
2694}
2695
2696// ------------------------------ EmptyStatementNode ---------------------------
2697
2698void EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2699{
2700 RELEASE_ASSERT(needsDebugHook());
2701}
2702
2703// ------------------------------ DebuggerStatementNode ---------------------------
2704
2705void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2706{
2707 generator.emitDebugHook(DidReachBreakpoint, position());
2708}
2709
2710// ------------------------------ ExprStatementNode ----------------------------
2711
2712void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2713{
2714 ASSERT(m_expr);
2715 generator.emitNode(dst, m_expr);
2716}
2717
2718// ------------------------------ DeclarationStatement ----------------------------
2719
2720void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2721{
2722 ASSERT(m_expr);
2723 generator.emitNode(m_expr);
2724}
2725
2726// ------------------------------ EmptyVarExpression ----------------------------
2727
2728RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2729{
2730 // It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
2731 if (!generator.shouldEmitTypeProfilerHooks())
2732 return nullptr;
2733
2734 Variable var = generator.variable(m_ident);
2735 if (RegisterID* local = var.local())
2736 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2737 else {
2738 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2739 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
2740 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2741 }
2742
2743 return nullptr;
2744}
2745
2746// ------------------------------ EmptyLetExpression ----------------------------
2747
2748RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2749{
2750 // Lexical declarations like 'let' must move undefined into their variables so we don't
2751 // get TDZ errors for situations like this: `let x; x;`
2752 Variable var = generator.variable(m_ident);
2753 if (RegisterID* local = var.local()) {
2754 generator.emitLoad(local, jsUndefined());
2755 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2756 } else {
2757 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2758 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
2759 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
2760 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
2761 }
2762
2763 generator.liftTDZCheckIfPossible(var);
2764
2765 // It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
2766 return nullptr;
2767}
2768
2769// ------------------------------ IfElseNode ---------------------------------------
2770
2771static inline StatementNode* singleStatement(StatementNode* statementNode)
2772{
2773 if (statementNode->isBlock())
2774 return static_cast<BlockNode*>(statementNode)->singleStatement();
2775 return statementNode;
2776}
2777
2778bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2779 Label*& trueTarget, FallThroughMode& fallThroughMode)
2780{
2781 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2782 if (!singleStatement)
2783 return false;
2784
2785 if (singleStatement->isBreak()) {
2786 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2787 Label* target = breakNode->trivialTarget(generator);
2788 if (!target)
2789 return false;
2790 trueTarget = target;
2791 fallThroughMode = FallThroughMeansFalse;
2792 return true;
2793 }
2794
2795 if (singleStatement->isContinue()) {
2796 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2797 Label* target = continueNode->trivialTarget(generator);
2798 if (!target)
2799 return false;
2800 trueTarget = target;
2801 fallThroughMode = FallThroughMeansFalse;
2802 return true;
2803 }
2804
2805 return false;
2806}
2807
2808void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2809{
2810 if (generator.shouldBeConcernedWithCompletionValue()) {
2811 if (m_ifBlock->hasEarlyBreakOrContinue() || (m_elseBlock && m_elseBlock->hasEarlyBreakOrContinue()))
2812 generator.emitLoad(dst, jsUndefined());
2813 }
2814
2815 Ref<Label> beforeThen = generator.newLabel();
2816 Ref<Label> beforeElse = generator.newLabel();
2817 Ref<Label> afterElse = generator.newLabel();
2818
2819 Label* trueTarget = beforeThen.ptr();
2820 Label& falseTarget = beforeElse.get();
2821 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2822 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2823
2824 generator.emitNodeInConditionContext(m_condition, *trueTarget, falseTarget, fallThroughMode);
2825 generator.emitLabel(beforeThen.get());
2826 generator.emitProfileControlFlow(m_ifBlock->startOffset());
2827
2828 if (!didFoldIfBlock) {
2829 generator.emitNodeInTailPosition(dst, m_ifBlock);
2830 if (m_elseBlock)
2831 generator.emitJump(afterElse.get());
2832 }
2833
2834 generator.emitLabel(beforeElse.get());
2835
2836 if (m_elseBlock) {
2837 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
2838 generator.emitNodeInTailPosition(dst, m_elseBlock);
2839 }
2840
2841 generator.emitLabel(afterElse.get());
2842 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2843 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
2844}
2845
2846// ------------------------------ DoWhileNode ----------------------------------
2847
2848void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2849{
2850 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
2851 generator.emitLoad(dst, jsUndefined());
2852
2853 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
2854
2855 Ref<Label> topOfLoop = generator.newLabel();
2856 generator.emitLabel(topOfLoop.get());
2857 generator.emitLoopHint();
2858
2859 generator.emitNodeInTailPosition(dst, m_statement);
2860
2861 generator.emitLabel(*scope->continueTarget());
2862 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2863
2864 generator.emitLabel(scope->breakTarget());
2865}
2866
2867// ------------------------------ WhileNode ------------------------------------
2868
2869void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2870{
2871 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
2872 generator.emitLoad(dst, jsUndefined());
2873
2874 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
2875 Ref<Label> topOfLoop = generator.newLabel();
2876
2877 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
2878
2879 generator.emitLabel(topOfLoop.get());
2880 generator.emitLoopHint();
2881
2882 generator.emitProfileControlFlow(m_statement->startOffset());
2883 generator.emitNodeInTailPosition(dst, m_statement);
2884
2885 generator.emitLabel(*scope->continueTarget());
2886
2887 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2888
2889 generator.emitLabel(scope->breakTarget());
2890
2891 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
2892}
2893
2894// ------------------------------ ForNode --------------------------------------
2895
2896void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2897{
2898 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
2899 generator.emitLoad(dst, jsUndefined());
2900
2901 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
2902
2903 RegisterID* forLoopSymbolTable = nullptr;
2904 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
2905
2906 if (m_expr1)
2907 generator.emitNode(generator.ignoredResult(), m_expr1);
2908
2909 Ref<Label> topOfLoop = generator.newLabel();
2910 if (m_expr2)
2911 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
2912
2913 generator.emitLabel(topOfLoop.get());
2914 generator.emitLoopHint();
2915 generator.emitProfileControlFlow(m_statement->startOffset());
2916
2917 generator.emitNodeInTailPosition(dst, m_statement);
2918
2919 generator.emitLabel(*scope->continueTarget());
2920 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
2921 if (m_expr3)
2922 generator.emitNode(generator.ignoredResult(), m_expr3);
2923
2924 if (m_expr2)
2925 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2926 else
2927 generator.emitJump(topOfLoop.get());
2928
2929 generator.emitLabel(scope->breakTarget());
2930 generator.popLexicalScope(this);
2931 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
2932}
2933
2934// ------------------------------ ForInNode ------------------------------------
2935
2936RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
2937{
2938 if (m_lexpr->isResolveNode()) {
2939 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2940 return generator.variable(ident).local();
2941 }
2942
2943 if (m_lexpr->isDestructuringNode()) {
2944 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
2945 auto binding = assignNode->bindings();
2946 if (!binding->isBindingNode())
2947 return nullptr;
2948
2949 auto simpleBinding = static_cast<BindingNode*>(binding);
2950 const Identifier& ident = simpleBinding->boundProperty();
2951 Variable var = generator.variable(ident);
2952 if (var.isSpecial())
2953 return nullptr;
2954 return var.local();
2955 }
2956
2957 return nullptr;
2958}
2959
2960void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2961{
2962 auto lambdaEmitResolveVariable = [&] (const Identifier& ident) {
2963 Variable var = generator.variable(ident);
2964 if (RegisterID* local = var.local()) {
2965 if (var.isReadOnly())
2966 generator.emitReadOnlyExceptionIfNeeded(var);
2967 generator.move(local, propertyName);
2968 } else {
2969 if (generator.isStrictMode())
2970 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2971 if (var.isReadOnly())
2972 generator.emitReadOnlyExceptionIfNeeded(var);
2973 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2974 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2975 generator.emitPutToScope(scope.get(), var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
2976 }
2977 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
2978 };
2979
2980 if (m_lexpr->isResolveNode()) {
2981 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2982 lambdaEmitResolveVariable(ident);
2983 return;
2984 }
2985
2986 if (m_lexpr->isAssignResolveNode()) {
2987 const Identifier& ident = static_cast<AssignResolveNode*>(m_lexpr)->identifier();
2988 lambdaEmitResolveVariable(ident);
2989 return;
2990 }
2991
2992 if (m_lexpr->isDotAccessorNode()) {
2993 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2994 const Identifier& ident = assignNode->identifier();
2995 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2996 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2997 if (assignNode->base()->isSuperNode()) {
2998 RefPtr<RegisterID> thisValue = generator.ensureThis();
2999 generator.emitPutById(base.get(), thisValue.get(), ident, propertyName);
3000 } else
3001 generator.emitPutById(base.get(), ident, propertyName);
3002 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
3003 return;
3004 }
3005 if (m_lexpr->isBracketAccessorNode()) {
3006 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
3007 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3008 RefPtr<RegisterID> subscript = generator.emitNodeForProperty(assignNode->subscript());
3009 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
3010 if (assignNode->base()->isSuperNode()) {
3011 RefPtr<RegisterID> thisValue = generator.ensureThis();
3012 generator.emitPutByVal(base.get(), thisValue.get(), subscript.get(), propertyName);
3013 } else
3014 generator.emitPutByVal(base.get(), subscript.get(), propertyName);
3015 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
3016 return;
3017 }
3018
3019 if (m_lexpr->isDestructuringNode()) {
3020 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
3021 auto binding = assignNode->bindings();
3022 if (!binding->isBindingNode()) {
3023 assignNode->bindings()->bindValue(generator, propertyName);
3024 return;
3025 }
3026
3027 auto simpleBinding = static_cast<BindingNode*>(binding);
3028 const Identifier& ident = simpleBinding->boundProperty();
3029 Variable var = generator.variable(ident);
3030 if (!var.local() || var.isSpecial()) {
3031 assignNode->bindings()->bindValue(generator, propertyName);
3032 return;
3033 }
3034 generator.move(var.local(), propertyName);
3035 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
3036 return;
3037 }
3038
3039 RELEASE_ASSERT_NOT_REACHED();
3040}
3041
3042void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3043{
3044 if (!m_lexpr->isAssignResolveNode() && !m_lexpr->isAssignmentLocation()) {
3045 emitThrowReferenceError(generator, "Left side of for-in statement is not a reference."_s);
3046 return;
3047 }
3048
3049 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
3050 generator.emitLoad(dst, jsUndefined());
3051
3052 Ref<Label> end = generator.newLabel();
3053
3054 RegisterID* forLoopSymbolTable = nullptr;
3055 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
3056
3057 if (m_lexpr->isAssignResolveNode())
3058 generator.emitNode(generator.ignoredResult(), m_lexpr);
3059
3060 RefPtr<RegisterID> base = generator.newTemporary();
3061 RefPtr<RegisterID> length;
3062 RefPtr<RegisterID> enumerator;
3063
3064 generator.emitNode(base.get(), m_expr);
3065 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
3066 RefPtr<RegisterID> enumeratorIndex;
3067
3068 // Pause at the assignment expression for each for..in iteration.
3069 generator.emitDebugHook(m_lexpr);
3070
3071 int profilerStartOffset = m_statement->startOffset();
3072 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
3073
3074 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
3075
3076 BytecodeGenerator::PreservedTDZStack preservedTDZStack;
3077 generator.preserveTDZStack(preservedTDZStack);
3078
3079 // Indexed property loop.
3080 {
3081 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
3082 Ref<Label> loopStart = generator.newLabel();
3083 Ref<Label> loopEnd = generator.newLabel();
3084
3085 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
3086 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
3087 RefPtr<RegisterID> propertyName = generator.newTemporary();
3088
3089 generator.emitLabel(loopStart.get());
3090 generator.emitLoopHint();
3091
3092 RefPtr<RegisterID> result = generator.emitEqualityOp<OpLess>(generator.newTemporary(), i.get(), length.get());
3093 generator.emitJumpIfFalse(result.get(), loopEnd.get());
3094 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
3095 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
3096
3097 generator.emitToIndexString(propertyName.get(), i.get());
3098 this->emitLoopHeader(generator, propertyName.get());
3099
3100 generator.emitProfileControlFlow(profilerStartOffset);
3101
3102 generator.pushIndexedForInScope(local.get(), i.get());
3103 generator.emitNode(dst, m_statement);
3104 generator.popIndexedForInScope(local.get());
3105
3106 generator.emitProfileControlFlow(profilerEndOffset);
3107
3108 generator.emitLabel(*scope->continueTarget());
3109 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
3110 generator.emitInc(i.get());
3111 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
3112 generator.emitJump(loopStart.get());
3113
3114 generator.emitLabel(scope->breakTarget());
3115 generator.emitJump(end.get());
3116 generator.emitLabel(loopEnd.get());
3117 }
3118 generator.restoreTDZStack(preservedTDZStack);
3119
3120 // Structure property loop.
3121 {
3122 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
3123 Ref<Label> loopStart = generator.newLabel();
3124 Ref<Label> loopEnd = generator.newLabel();
3125
3126 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
3127 RefPtr<RegisterID> propertyName = generator.newTemporary();
3128 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3129
3130 generator.emitLabel(loopStart.get());
3131 generator.emitLoopHint();
3132
3133 RefPtr<RegisterID> result = generator.emitUnaryOp<OpEqNull>(generator.newTemporary(), propertyName.get());
3134 generator.emitJumpIfTrue(result.get(), loopEnd.get());
3135 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
3136 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
3137
3138 this->emitLoopHeader(generator, propertyName.get());
3139
3140 generator.emitProfileControlFlow(profilerStartOffset);
3141
3142 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
3143 generator.emitNode(dst, m_statement);
3144 generator.popStructureForInScope(local.get());
3145
3146 generator.emitProfileControlFlow(profilerEndOffset);
3147
3148 generator.emitLabel(*scope->continueTarget());
3149 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
3150 generator.emitInc(enumeratorIndex.get());
3151 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3152 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
3153 generator.emitJump(loopStart.get());
3154
3155 generator.emitLabel(scope->breakTarget());
3156 generator.emitJump(end.get());
3157 generator.emitLabel(loopEnd.get());
3158 }
3159 generator.restoreTDZStack(preservedTDZStack);
3160
3161 // Generic property loop.
3162 {
3163 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
3164 Ref<Label> loopStart = generator.newLabel();
3165 Ref<Label> loopEnd = generator.newLabel();
3166
3167 RefPtr<RegisterID> propertyName = generator.newTemporary();
3168
3169 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3170
3171 generator.emitLabel(loopStart.get());
3172 generator.emitLoopHint();
3173
3174 RefPtr<RegisterID> result = generator.emitUnaryOp<OpEqNull>(generator.newTemporary(), propertyName.get());
3175 generator.emitJumpIfTrue(result.get(), loopEnd.get());
3176
3177 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
3178 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
3179
3180 this->emitLoopHeader(generator, propertyName.get());
3181
3182 generator.emitProfileControlFlow(profilerStartOffset);
3183
3184 generator.emitNode(dst, m_statement);
3185
3186 generator.emitLabel(*scope->continueTarget());
3187 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
3188 generator.emitInc(enumeratorIndex.get());
3189 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
3190 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
3191 generator.emitJump(loopStart.get());
3192
3193 generator.emitLabel(scope->breakTarget());
3194 generator.emitJump(end.get());
3195 generator.emitLabel(loopEnd.get());
3196 }
3197
3198 generator.emitLabel(end.get());
3199 generator.popLexicalScope(this);
3200 generator.emitProfileControlFlow(profilerEndOffset);
3201}
3202
3203// ------------------------------ ForOfNode ------------------------------------
3204void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3205{
3206 if (!m_lexpr->isAssignmentLocation()) {
3207 emitThrowReferenceError(generator, "Left side of for-of statement is not a reference."_s);
3208 return;
3209 }
3210
3211 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
3212 generator.emitLoad(dst, jsUndefined());
3213
3214 RegisterID* forLoopSymbolTable = nullptr;
3215 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
3216 auto extractor = scopedLambda<void(BytecodeGenerator&, RegisterID*)>([this, dst](BytecodeGenerator& generator, RegisterID* value)
3217 {
3218 if (m_lexpr->isResolveNode()) {
3219 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
3220 Variable var = generator.variable(ident);
3221 if (RegisterID* local = var.local()) {
3222 if (var.isReadOnly())
3223 generator.emitReadOnlyExceptionIfNeeded(var);
3224 generator.move(local, value);
3225 } else {
3226 if (generator.isStrictMode())
3227 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
3228 if (var.isReadOnly())
3229 generator.emitReadOnlyExceptionIfNeeded(var);
3230 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
3231 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
3232 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
3233 }
3234 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
3235 } else if (m_lexpr->isDotAccessorNode()) {
3236 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
3237 const Identifier& ident = assignNode->identifier();
3238 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3239
3240 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
3241 if (assignNode->base()->isSuperNode()) {
3242 RefPtr<RegisterID> thisValue = generator.ensureThis();
3243 generator.emitPutById(base.get(), thisValue.get(), ident, value);
3244 } else
3245 generator.emitPutById(base.get(), ident, value);
3246 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
3247 } else if (m_lexpr->isBracketAccessorNode()) {
3248 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
3249 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3250 RegisterID* subscript = generator.emitNodeForProperty(assignNode->subscript());
3251
3252 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
3253 if (assignNode->base()->isSuperNode()) {
3254 RefPtr<RegisterID> thisValue = generator.ensureThis();
3255 generator.emitPutByVal(base.get(), thisValue.get(), subscript, value);
3256 } else
3257 generator.emitPutByVal(base.get(), subscript, value);
3258 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
3259 } else {
3260 ASSERT(m_lexpr->isDestructuringNode());
3261 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
3262 assignNode->bindings()->bindValue(generator, value);
3263 }
3264 generator.emitProfileControlFlow(m_statement->startOffset());
3265 generator.emitNode(dst, m_statement);
3266 });
3267 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
3268 generator.popLexicalScope(this);
3269 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
3270}
3271
3272// ------------------------------ ContinueNode ---------------------------------
3273
3274Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
3275{
3276 if (generator.shouldEmitDebugHooks())
3277 return nullptr;
3278
3279 LabelScope* scope = generator.continueTarget(m_ident);
3280 ASSERT(scope);
3281
3282 if (generator.labelScopeDepth() != scope->scopeDepth())
3283 return nullptr;
3284
3285 return scope->continueTarget();
3286}
3287
3288void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3289{
3290 LabelScope* scope = generator.continueTarget(m_ident);
3291 ASSERT(scope);
3292
3293 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), *scope->continueTarget());
3294 if (!hasFinally) {
3295 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3296 generator.restoreScopeRegister(lexicalScopeIndex);
3297 generator.emitJump(*scope->continueTarget());
3298 }
3299
3300 generator.emitProfileControlFlow(endOffset());
3301}
3302
3303// ------------------------------ BreakNode ------------------------------------
3304
3305Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
3306{
3307 if (generator.shouldEmitDebugHooks())
3308 return nullptr;
3309
3310 LabelScope* scope = generator.breakTarget(m_ident);
3311 ASSERT(scope);
3312
3313 if (generator.labelScopeDepth() != scope->scopeDepth())
3314 return nullptr;
3315
3316 return &scope->breakTarget();
3317}
3318
3319void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3320{
3321 LabelScope* scope = generator.breakTarget(m_ident);
3322 ASSERT(scope);
3323
3324 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget());
3325 if (!hasFinally) {
3326 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3327 generator.restoreScopeRegister(lexicalScopeIndex);
3328 generator.emitJump(scope->breakTarget());
3329 }
3330
3331 generator.emitProfileControlFlow(endOffset());
3332}
3333
3334// ------------------------------ ReturnNode -----------------------------------
3335
3336void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3337{
3338 ASSERT(generator.codeType() == FunctionCode);
3339
3340 if (dst == generator.ignoredResult())
3341 dst = 0;
3342
3343 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
3344
3345 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
3346
3347 bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());
3348 if (!hasFinally) {
3349 if (generator.parseMode() == SourceParseMode::AsyncGeneratorBodyMode) {
3350 returnRegister = generator.move(generator.newTemporary(), returnRegister.get());
3351 generator.emitAwait(returnRegister.get());
3352 }
3353
3354 generator.emitWillLeaveCallFrameDebugHook();
3355 generator.emitReturn(returnRegister.get());
3356 }
3357
3358 generator.emitProfileControlFlow(endOffset());
3359 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
3360 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
3361 if (generator.shouldEmitControlFlowProfilerHooks())
3362 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
3363}
3364
3365// ------------------------------ WithNode -------------------------------------
3366
3367void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3368{
3369 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
3370 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
3371 generator.emitPushWithScope(scope.get());
3372 if (generator.shouldBeConcernedWithCompletionValue() && m_statement->hasEarlyBreakOrContinue())
3373 generator.emitLoad(dst, jsUndefined());
3374 generator.emitNodeInTailPosition(dst, m_statement);
3375 generator.emitPopWithScope();
3376}
3377
3378// ------------------------------ CaseClauseNode --------------------------------
3379
3380inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3381{
3382 generator.emitProfileControlFlow(m_startOffset);
3383 if (!m_statements)
3384 return;
3385 m_statements->emitBytecode(generator, dst);
3386}
3387
3388// ------------------------------ CaseBlockNode --------------------------------
3389
3390enum SwitchKind {
3391 SwitchUnset = 0,
3392 SwitchNumber = 1,
3393 SwitchString = 2,
3394 SwitchNeither = 3
3395};
3396
3397static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
3398{
3399 for (; list; list = list->getNext()) {
3400 ExpressionNode* clauseExpression = list->getClause()->expr();
3401 literalVector.append(clauseExpression);
3402 if (clauseExpression->isNumber()) {
3403 double value = static_cast<NumberNode*>(clauseExpression)->value();
3404 int32_t intVal = static_cast<int32_t>(value);
3405 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
3406 typeForTable = SwitchNeither;
3407 break;
3408 }
3409 if (intVal < min_num)
3410 min_num = intVal;
3411 if (intVal > max_num)
3412 max_num = intVal;
3413 typeForTable = SwitchNumber;
3414 continue;
3415 }
3416 if (clauseExpression->isString()) {
3417 if (typeForTable & ~SwitchString) {
3418 typeForTable = SwitchNeither;
3419 break;
3420 }
3421 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
3422 if (singleCharacterSwitch &= value.length() == 1) {
3423 int32_t intVal = value[0];
3424 if (intVal < min_num)
3425 min_num = intVal;
3426 if (intVal > max_num)
3427 max_num = intVal;
3428 }
3429 typeForTable = SwitchString;
3430 continue;
3431 }
3432 typeForTable = SwitchNeither;
3433 break;
3434 }
3435}
3436
3437static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
3438{
3439 size_t length = 0;
3440 for (ClauseListNode* node = list1; node; node = node->getNext())
3441 ++length;
3442 for (ClauseListNode* node = list2; node; node = node->getNext())
3443 ++length;
3444 return length;
3445}
3446
3447SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
3448{
3449 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
3450 return SwitchInfo::SwitchNone;
3451
3452 SwitchKind typeForTable = SwitchUnset;
3453 bool singleCharacterSwitch = true;
3454
3455 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3456 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3457
3458 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
3459 return SwitchInfo::SwitchNone;
3460
3461 if (typeForTable == SwitchNumber) {
3462 int32_t range = max_num - min_num;
3463 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3464 return SwitchInfo::SwitchImmediate;
3465 return SwitchInfo::SwitchNone;
3466 }
3467
3468 ASSERT(typeForTable == SwitchString);
3469
3470 if (singleCharacterSwitch) {
3471 int32_t range = max_num - min_num;
3472 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3473 return SwitchInfo::SwitchCharacter;
3474 }
3475
3476 return SwitchInfo::SwitchString;
3477}
3478
3479void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
3480{
3481 Vector<Ref<Label>, 8> labelVector;
3482 Vector<ExpressionNode*, 8> literalVector;
3483 int32_t min_num = std::numeric_limits<int32_t>::max();
3484 int32_t max_num = std::numeric_limits<int32_t>::min();
3485 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
3486
3487 Ref<Label> defaultLabel = generator.newLabel();
3488 if (switchType != SwitchInfo::SwitchNone) {
3489 // Prepare the various labels
3490 for (uint32_t i = 0; i < literalVector.size(); i++)
3491 labelVector.append(generator.newLabel());
3492 generator.beginSwitch(switchExpression, switchType);
3493 } else {
3494 // Setup jumps
3495 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3496 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3497 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3498 generator.emitBinaryOp<OpStricteq>(clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3499 labelVector.append(generator.newLabel());
3500 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3501 }
3502
3503 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3504 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3505 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3506 generator.emitBinaryOp<OpStricteq>(clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3507 labelVector.append(generator.newLabel());
3508 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3509 }
3510 generator.emitJump(defaultLabel.get());
3511 }
3512
3513 size_t i = 0;
3514 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3515 generator.emitLabel(labelVector[i++].get());
3516 list->getClause()->emitBytecode(generator, dst);
3517 }
3518
3519 if (m_defaultClause) {
3520 generator.emitLabel(defaultLabel.get());
3521 m_defaultClause->emitBytecode(generator, dst);
3522 }
3523
3524 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3525 generator.emitLabel(labelVector[i++].get());
3526 list->getClause()->emitBytecode(generator, dst);
3527 }
3528 if (!m_defaultClause)
3529 generator.emitLabel(defaultLabel.get());
3530
3531 ASSERT(i == labelVector.size());
3532 if (switchType != SwitchInfo::SwitchNone) {
3533 ASSERT(labelVector.size() == literalVector.size());
3534 generator.endSwitch(labelVector.size(), labelVector, literalVector.data(), defaultLabel.get(), min_num, max_num);
3535 }
3536}
3537
3538// ------------------------------ SwitchNode -----------------------------------
3539
3540void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3541{
3542 if (generator.shouldBeConcernedWithCompletionValue())
3543 generator.emitLoad(dst, jsUndefined());
3544
3545 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
3546
3547 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
3548
3549 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::DoNotOptimize, BytecodeGenerator::NestedScopeType::IsNested);
3550 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
3551 generator.popLexicalScope(this);
3552
3553 generator.emitLabel(scope->breakTarget());
3554 generator.emitProfileControlFlow(endOffset());
3555}
3556
3557// ------------------------------ LabelNode ------------------------------------
3558
3559void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3560{
3561 ASSERT(!generator.breakTarget(m_name));
3562
3563 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
3564 generator.emitNodeInTailPosition(dst, m_statement);
3565
3566 generator.emitLabel(scope->breakTarget());
3567}
3568
3569// ------------------------------ ThrowNode ------------------------------------
3570
3571void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3572{
3573 if (dst == generator.ignoredResult())
3574 dst = 0;
3575 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
3576 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
3577 generator.emitThrow(expr.get());
3578
3579 generator.emitProfileControlFlow(endOffset());
3580}
3581
3582// ------------------------------ TryNode --------------------------------------
3583
3584void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3585{
3586 // NOTE: The catch and finally blocks must be labeled explicitly, so the
3587 // optimizer knows they may be jumped to from anywhere.
3588
3589 if (generator.shouldBeConcernedWithCompletionValue() && m_tryBlock->hasEarlyBreakOrContinue())
3590 generator.emitLoad(dst, jsUndefined());
3591
3592 ASSERT(m_catchBlock || m_finallyBlock);
3593
3594 RefPtr<Label> catchLabel;
3595 RefPtr<Label> catchEndLabel;
3596 RefPtr<Label> finallyLabel;
3597 RefPtr<Label> finallyEndLabel;
3598 Optional<FinallyContext> finallyContext;
3599
3600 if (m_finallyBlock) {
3601 finallyLabel = generator.newLabel();
3602 finallyEndLabel = generator.newLabel();
3603
3604 finallyContext.emplace(generator, *finallyLabel);
3605 generator.pushFinallyControlFlowScope(finallyContext.value());
3606 }
3607 if (m_catchBlock) {
3608 catchLabel = generator.newLabel();
3609 catchEndLabel = generator.newLabel();
3610 }
3611
3612 Ref<Label> tryLabel = generator.newEmittedLabel();
3613 Label& tryHandlerLabel = m_catchBlock ? *catchLabel : *finallyLabel;
3614 HandlerType tryHandlerType = m_catchBlock ? HandlerType::Catch : HandlerType::Finally;
3615 TryData* tryData = generator.pushTry(tryLabel.get(), tryHandlerLabel, tryHandlerType);
3616 TryData* finallyTryData = nullptr;
3617 if (!m_catchBlock && m_finallyBlock)
3618 finallyTryData = tryData;
3619
3620 generator.emitNode(dst, m_tryBlock);
3621
3622 if (m_finallyBlock)
3623 generator.emitJump(*finallyLabel);
3624 else
3625 generator.emitJump(*catchEndLabel);
3626
3627 Ref<Label> tryEndLabel = generator.newEmittedLabel();
3628 generator.popTry(tryData, tryEndLabel.get());
3629
3630 if (m_catchBlock) {
3631 // Uncaught exception path: the catch block.
3632 generator.emitLabel(*catchLabel);
3633 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
3634 RegisterID* completionTypeRegister = m_finallyBlock ? finallyContext->completionTypeRegister() : nullptr;
3635 generator.emitOutOfLineCatchHandler(thrownValueRegister.get(), completionTypeRegister, tryData);
3636 generator.restoreScopeRegister();
3637
3638 if (m_finallyBlock) {
3639 // If the catch block throws an exception and we have a finally block, then the finally
3640 // block should "catch" that exception.
3641 finallyTryData = generator.pushTry(*catchLabel, *finallyLabel, HandlerType::Finally);
3642 }
3643
3644 if (m_catchPattern) {
3645 generator.emitPushCatchScope(m_lexicalVariables);
3646 m_catchPattern->bindValue(generator, thrownValueRegister.get());
3647 }
3648
3649 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
3650 if (m_finallyBlock)
3651 generator.emitNode(dst, m_catchBlock);
3652 else
3653 generator.emitNodeInTailPosition(dst, m_catchBlock);
3654 generator.emitLoad(thrownValueRegister.get(), jsUndefined());
3655
3656 if (m_catchPattern)
3657 generator.emitPopCatchScope(m_lexicalVariables);
3658
3659 if (m_finallyBlock) {
3660 generator.emitLoad(finallyContext->completionTypeRegister(), CompletionType::Normal);
3661 generator.emitJump(*finallyLabel);
3662 generator.popTry(finallyTryData, *finallyLabel);
3663 }
3664
3665 generator.emitLabel(*catchEndLabel);
3666 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
3667 }
3668
3669 if (m_finallyBlock) {
3670 generator.popFinallyControlFlowScope();
3671
3672 // Entry to the finally block for CompletionType::Throw to be generated later.
3673 generator.emitOutOfLineFinallyHandler(finallyContext->completionValueRegister(), finallyContext->completionTypeRegister(), finallyTryData);
3674
3675 // Entry to the finally block for CompletionTypes other than Throw.
3676 generator.emitLabel(*finallyLabel);
3677 generator.restoreScopeRegister();
3678
3679 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
3680 generator.emitProfileControlFlow(finallyStartOffset);
3681 generator.emitNodeInTailPosition(m_finallyBlock);
3682
3683 generator.emitFinallyCompletion(finallyContext.value(), *finallyEndLabel);
3684 generator.emitLabel(*finallyEndLabel);
3685 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
3686 }
3687}
3688
3689// ------------------------------ ScopeNode -----------------------------
3690
3691inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
3692{
3693 if (!m_statements)
3694 return;
3695 m_statements->emitBytecode(generator, dst);
3696}
3697
3698static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
3699{
3700 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
3701
3702 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3703 generator.emitLoad(dstRegister.get(), jsUndefined());
3704 generator.emitProfileControlFlow(scopeNode.startStartOffset());
3705 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
3706
3707 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
3708 generator.emitEnd(dstRegister.get());
3709}
3710
3711// ------------------------------ ProgramNode -----------------------------
3712
3713void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3714{
3715 emitProgramNodeBytecode(generator, *this);
3716}
3717
3718// ------------------------------ ModuleProgramNode --------------------
3719
3720void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3721{
3722 emitProgramNodeBytecode(generator, *this);
3723}
3724
3725// ------------------------------ EvalNode -----------------------------
3726
3727void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3728{
3729 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
3730
3731 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3732 generator.emitLoad(dstRegister.get(), jsUndefined());
3733 emitStatementsBytecode(generator, dstRegister.get());
3734
3735 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
3736 generator.emitEnd(dstRegister.get());
3737}
3738
3739// ------------------------------ FunctionNode -----------------------------
3740
3741void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3742{
3743 if (generator.shouldEmitTypeProfilerHooks()) {
3744 // If the parameter list is non simple one, it is handled in bindValue's code.
3745 if (m_parameters->isSimpleParameterList()) {
3746 for (size_t i = 0; i < m_parameters->size(); i++) {
3747 BindingNode* bindingNode = static_cast<BindingNode*>(m_parameters->at(i).first);
3748 RegisterID reg(CallFrame::argumentOffset(i));
3749 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, bindingNode->divotStart(), bindingNode->divotEnd());
3750 }
3751 }
3752 }
3753
3754 generator.emitProfileControlFlow(startStartOffset());
3755 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
3756
3757 switch (generator.parseMode()) {
3758 case SourceParseMode::GeneratorWrapperFunctionMode:
3759 case SourceParseMode::GeneratorWrapperMethodMode:
3760 case SourceParseMode::AsyncGeneratorWrapperMethodMode:
3761 case SourceParseMode::AsyncGeneratorWrapperFunctionMode: {
3762 StatementNode* singleStatement = this->singleStatement();
3763 ASSERT(singleStatement->isExprStatement());
3764 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3765 ExpressionNode* expr = exprStatement->expr();
3766 ASSERT(expr->isFuncExprNode());
3767 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
3768
3769 RefPtr<RegisterID> next = generator.newTemporary();
3770 generator.emitNode(next.get(), funcExpr);
3771
3772 if (generator.superBinding() == SuperBinding::Needed) {
3773 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3774 emitPutHomeObject(generator, next.get(), homeObject.get());
3775 }
3776
3777 if (isGeneratorWrapperParseMode(generator.parseMode()))
3778 generator.emitPutGeneratorFields(next.get());
3779 else {
3780 ASSERT(isAsyncGeneratorWrapperParseMode(generator.parseMode()));
3781 generator.emitPutAsyncGeneratorFields(next.get());
3782 }
3783
3784 ASSERT(startOffset() >= lineStartOffset());
3785 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3786 generator.emitReturn(generator.generatorRegister());
3787 break;
3788 }
3789
3790 case SourceParseMode::AsyncFunctionMode:
3791 case SourceParseMode::AsyncMethodMode:
3792 case SourceParseMode::AsyncArrowFunctionMode: {
3793 StatementNode* singleStatement = this->singleStatement();
3794 ASSERT(singleStatement->isExprStatement());
3795 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3796 ExpressionNode* expr = exprStatement->expr();
3797 ASSERT(expr->isFuncExprNode());
3798 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
3799
3800 RefPtr<RegisterID> next = generator.newTemporary();
3801 generator.emitNode(next.get(), funcExpr);
3802
3803 if (generator.superBinding() == SuperBinding::Needed || (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isSuperUsedInInnerArrowFunction())) {
3804 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3805 emitPutHomeObject(generator, next.get(), homeObject.get());
3806 }
3807
3808 if (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isThisUsedInInnerArrowFunction())
3809 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
3810
3811 generator.emitPutGeneratorFields(next.get());
3812
3813 ASSERT(startOffset() >= lineStartOffset());
3814 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3815
3816 // load and call @asyncFunctionResume
3817 auto var = generator.variable(generator.propertyNames().builtinNames().asyncFunctionResumePrivateName());
3818 RefPtr<RegisterID> scope = generator.newTemporary();
3819 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
3820 RefPtr<RegisterID> asyncFunctionResume = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
3821
3822 CallArguments args(generator, nullptr, 4);
3823 unsigned argumentCount = 0;
3824 generator.emitLoad(args.thisRegister(), jsUndefined());
3825 generator.move(args.argumentRegister(argumentCount++), generator.generatorRegister());
3826 generator.move(args.argumentRegister(argumentCount++), generator.promiseCapabilityRegister());
3827 generator.emitLoad(args.argumentRegister(argumentCount++), jsUndefined());
3828 generator.emitLoad(args.argumentRegister(argumentCount++), jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
3829 // JSTextPosition(int _line, int _offset, int _lineStartOffset)
3830 JSTextPosition divot(firstLine(), startOffset(), lineStartOffset());
3831
3832 RefPtr<RegisterID> result = generator.newTemporary();
3833 generator.emitCallInTailPosition(result.get(), asyncFunctionResume.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
3834 generator.emitReturn(result.get());
3835 break;
3836 }
3837
3838 case SourceParseMode::AsyncGeneratorBodyMode:
3839 case SourceParseMode::AsyncArrowFunctionBodyMode:
3840 case SourceParseMode::AsyncFunctionBodyMode:
3841 case SourceParseMode::GeneratorBodyMode: {
3842 Ref<Label> generatorBodyLabel = generator.newLabel();
3843 {
3844 RefPtr<RegisterID> condition = generator.newTemporary();
3845 generator.emitEqualityOp<OpStricteq>(condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))));
3846 generator.emitJumpIfTrue(condition.get(), generatorBodyLabel.get());
3847
3848 Ref<Label> throwLabel = generator.newLabel();
3849 generator.emitEqualityOp<OpStricteq>(condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))));
3850 generator.emitJumpIfTrue(condition.get(), throwLabel.get());
3851
3852 generator.emitReturn(generator.generatorValueRegister());
3853
3854 generator.emitLabel(throwLabel.get());
3855 generator.emitThrow(generator.generatorValueRegister());
3856 }
3857
3858 generator.emitLabel(generatorBodyLabel.get());
3859
3860 emitStatementsBytecode(generator, generator.ignoredResult());
3861
3862 Ref<Label> done = generator.newLabel();
3863 generator.emitLabel(done.get());
3864 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
3865 break;
3866 }
3867
3868 default: {
3869 emitStatementsBytecode(generator, generator.ignoredResult());
3870
3871 StatementNode* singleStatement = this->singleStatement();
3872 ReturnNode* returnNode = 0;
3873
3874 // Check for a return statement at the end of a function composed of a single block.
3875 if (singleStatement && singleStatement->isBlock()) {
3876 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
3877 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
3878 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
3879 }
3880
3881 // If there is no return we must automatically insert one.
3882 if (!returnNode) {
3883 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isSuperCallUsedInInnerArrowFunction())
3884 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
3885
3886 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
3887 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
3888 ASSERT(startOffset() >= lineStartOffset());
3889 generator.emitWillLeaveCallFrameDebugHook();
3890 generator.emitReturn(r0);
3891 return;
3892 }
3893 break;
3894 }
3895 }
3896}
3897
3898// ------------------------------ FuncDeclNode ---------------------------------
3899
3900void FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3901{
3902 generator.hoistSloppyModeFunctionIfNecessary(metadata()->ident());
3903}
3904
3905// ------------------------------ FuncExprNode ---------------------------------
3906
3907RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3908{
3909 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3910}
3911
3912// ------------------------------ ArrowFuncExprNode ---------------------------------
3913
3914RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3915{
3916 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3917}
3918
3919// ------------------------------ MethodDefinitionNode ---------------------------------
3920
3921RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3922{
3923 return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
3924}
3925
3926// ------------------------------ YieldExprNode --------------------------------
3927
3928RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3929{
3930 if (!delegate()) {
3931 RefPtr<RegisterID> arg = nullptr;
3932 if (argument()) {
3933 arg = generator.newTemporary();
3934 generator.emitNode(arg.get(), argument());
3935 } else
3936 arg = generator.emitLoad(nullptr, jsUndefined());
3937 RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield);
3938 if (dst == generator.ignoredResult())
3939 return nullptr;
3940 return generator.move(generator.finalDestination(dst), value.get());
3941 }
3942 RefPtr<RegisterID> arg = generator.newTemporary();
3943 generator.emitNode(arg.get(), argument());
3944 RefPtr<RegisterID> value = generator.emitDelegateYield(arg.get(), this);
3945 if (dst == generator.ignoredResult())
3946 return nullptr;
3947 return generator.move(generator.finalDestination(dst), value.get());
3948}
3949
3950// ------------------------------ AwaitExprNode --------------------------------
3951
3952RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3953{
3954 RefPtr<RegisterID> arg = generator.newTemporary();
3955 generator.emitNode(arg.get(), argument());
3956 RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Await);
3957 if (dst == generator.ignoredResult())
3958 return nullptr;
3959 return generator.move(generator.finalDestination(dst), value.get());
3960}
3961
3962// ------------------------------ ClassDeclNode ---------------------------------
3963
3964void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
3965{
3966 generator.emitNode(m_classDeclaration);
3967}
3968
3969// ------------------------------ ClassExprNode ---------------------------------
3970
3971RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3972{
3973 if (!m_name.isNull())
3974 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
3975
3976 RefPtr<RegisterID> superclass;
3977 if (m_classHeritage) {
3978 superclass = generator.newTemporary();
3979 generator.emitNode(superclass.get(), m_classHeritage);
3980 }
3981
3982 RefPtr<RegisterID> constructor;
3983 bool needsHomeObject = false;
3984
3985 if (m_constructorExpression) {
3986 ASSERT(m_constructorExpression->isFuncExprNode());
3987 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata();
3988 metadata->setEcmaName(ecmaName());
3989 metadata->setClassSource(m_classSource);
3990 constructor = generator.emitNode(dst, m_constructorExpression);
3991 needsHomeObject = m_classHeritage || metadata->superBinding() == SuperBinding::Needed;
3992 } else
3993 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3994
3995 const auto& propertyNames = generator.propertyNames();
3996 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
3997
3998 if (superclass) {
3999 RefPtr<RegisterID> protoParent = generator.newTemporary();
4000 generator.emitLoad(protoParent.get(), jsNull());
4001
4002 RefPtr<RegisterID> tempRegister = generator.newTemporary();
4003
4004 // FIXME: Throw TypeError if it's a generator function.
4005 Ref<Label> superclassIsUndefinedLabel = generator.newLabel();
4006 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
4007
4008 Ref<Label> superclassIsNullLabel = generator.newLabel();
4009 generator.emitJumpIfTrue(generator.emitUnaryOp<OpEqNull>(tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
4010
4011 Ref<Label> superclassIsObjectLabel = generator.newLabel();
4012 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
4013 generator.emitLabel(superclassIsUndefinedLabel.get());
4014 generator.emitThrowTypeError("The superclass is not an object."_s);
4015 generator.emitLabel(superclassIsObjectLabel.get());
4016 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
4017
4018 Ref<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
4019 generator.emitJumpIfTrue(generator.emitUnaryOp<OpIsObjectOrNull>(tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
4020 generator.emitJumpIfTrue(generator.emitUnaryOp<OpIsFunction>(tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
4021 generator.emitThrowTypeError("The value of the superclass's prototype property is not an object."_s);
4022 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
4023
4024 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
4025 generator.emitLabel(superclassIsNullLabel.get());
4026 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
4027 }
4028
4029 if (needsHomeObject)
4030 emitPutHomeObject(generator, constructor.get(), prototype.get());
4031
4032 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
4033 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
4034 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
4035
4036 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
4037 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
4038
4039 if (m_classElements)
4040 generator.emitDefineClassElements(m_classElements, constructor.get(), prototype.get());
4041
4042 if (!m_name.isNull()) {
4043 Variable classNameVar = generator.variable(m_name);
4044 RELEASE_ASSERT(classNameVar.isResolved());
4045 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
4046 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
4047 generator.popLexicalScope(this);
4048 }
4049
4050 return generator.move(dst, constructor.get());
4051}
4052
4053// ------------------------------ ImportDeclarationNode -----------------------
4054
4055void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4056{
4057 // Do nothing at runtime.
4058}
4059
4060// ------------------------------ ExportAllDeclarationNode --------------------
4061
4062void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4063{
4064 // Do nothing at runtime.
4065}
4066
4067// ------------------------------ ExportDefaultDeclarationNode ----------------
4068
4069void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4070{
4071 ASSERT(m_declaration);
4072 generator.emitNode(dst, m_declaration);
4073}
4074
4075// ------------------------------ ExportLocalDeclarationNode ------------------
4076
4077void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4078{
4079 ASSERT(m_declaration);
4080 generator.emitNode(dst, m_declaration);
4081}
4082
4083// ------------------------------ ExportNamedDeclarationNode ------------------
4084
4085void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4086{
4087 // Do nothing at runtime.
4088}
4089
4090// ------------------------------ DestructuringAssignmentNode -----------------
4091RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4092{
4093 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
4094 return result;
4095 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
4096 generator.emitNode(initializer.get(), m_initializer);
4097 m_bindings->bindValue(generator, initializer.get());
4098 return generator.move(dst, initializer.get());
4099}
4100
4101static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
4102{
4103 ASSERT(defaultValue);
4104 Ref<Label> isNotUndefined = generator.newLabel();
4105 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
4106 generator.emitNode(maybeUndefined, defaultValue);
4107 generator.emitLabel(isNotUndefined.get());
4108}
4109
4110void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
4111{
4112 RefPtr<RegisterID> iterator = generator.newTemporary();
4113 {
4114 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
4115 CallArguments args(generator, nullptr);
4116 generator.move(args.thisRegister(), rhs);
4117 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4118 }
4119 RefPtr<RegisterID> nextMethod = generator.emitGetById(generator.newTemporary(), iterator.get(), generator.propertyNames().next);
4120
4121 if (m_targetPatterns.isEmpty()) {
4122 generator.emitIteratorClose(iterator.get(), this);
4123 return;
4124 }
4125
4126 RefPtr<RegisterID> done;
4127 for (auto& target : m_targetPatterns) {
4128 switch (target.bindingType) {
4129 case BindingType::Elision:
4130 case BindingType::Element: {
4131 Ref<Label> iterationSkipped = generator.newLabel();
4132 if (!done)
4133 done = generator.newTemporary();
4134 else
4135 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
4136
4137 RefPtr<RegisterID> value = generator.newTemporary();
4138 generator.emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), this);
4139 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
4140 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
4141 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
4142
4143 {
4144 Ref<Label> valueIsSet = generator.newLabel();
4145 generator.emitJump(valueIsSet.get());
4146 generator.emitLabel(iterationSkipped.get());
4147 generator.emitLoad(value.get(), jsUndefined());
4148 generator.emitLabel(valueIsSet.get());
4149 }
4150
4151 if (target.bindingType == BindingType::Element) {
4152 if (target.defaultValue)
4153 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
4154 target.pattern->bindValue(generator, value.get());
4155 }
4156 break;
4157 }
4158
4159 case BindingType::RestElement: {
4160 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), nullptr, 0, ArrayWithUndecided);
4161
4162 Ref<Label> iterationDone = generator.newLabel();
4163 if (!done)
4164 done = generator.newTemporary();
4165 else
4166 generator.emitJumpIfTrue(done.get(), iterationDone.get());
4167
4168 RefPtr<RegisterID> index = generator.newTemporary();
4169 generator.emitLoad(index.get(), jsNumber(0));
4170 Ref<Label> loopStart = generator.newLabel();
4171 generator.emitLabel(loopStart.get());
4172
4173 RefPtr<RegisterID> value = generator.newTemporary();
4174 generator.emitIteratorNext(value.get(), nextMethod.get(), iterator.get(), this);
4175 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
4176 generator.emitJumpIfTrue(done.get(), iterationDone.get());
4177 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
4178
4179 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
4180 generator.emitInc(index.get());
4181 generator.emitJump(loopStart.get());
4182
4183 generator.emitLabel(iterationDone.get());
4184 target.pattern->bindValue(generator, array.get());
4185 break;
4186 }
4187 }
4188 }
4189
4190 Ref<Label> iteratorClosed = generator.newLabel();
4191 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
4192 generator.emitIteratorClose(iterator.get(), this);
4193 generator.emitLabel(iteratorClosed.get());
4194}
4195
4196RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
4197{
4198 if (!rhs->isSimpleArray())
4199 return nullptr;
4200
4201 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
4202 Vector<ExpressionNode*> elements;
4203 for (; elementNodes; elementNodes = elementNodes->next()) {
4204 ExpressionNode* value = elementNodes->value();
4205 if (value->isSpreadExpression())
4206 return nullptr;
4207 elements.append(value);
4208 }
4209
4210 RefPtr<RegisterID> resultRegister;
4211 if (dst != generator.ignoredResult())
4212 resultRegister = generator.emitNewArray(generator.newTemporary(), nullptr, 0, ArrayWithUndecided);
4213 if (m_targetPatterns.size() != elements.size())
4214 return nullptr;
4215 Vector<RefPtr<RegisterID>> registers;
4216 registers.reserveCapacity(m_targetPatterns.size());
4217 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4218 registers.uncheckedAppend(generator.newTemporary());
4219 generator.emitNode(registers.last().get(), elements[i]);
4220 if (m_targetPatterns[i].defaultValue)
4221 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
4222 if (resultRegister) {
4223 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(i));
4224 generator.emitDirectPutByVal(resultRegister.get(), index.get(), registers.last().get());
4225 }
4226 }
4227
4228 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4229 if (m_targetPatterns[i].pattern)
4230 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
4231 }
4232 if (resultRegister)
4233 return generator.move(generator.finalDestination(dst, resultRegister.get()), resultRegister.get());
4234 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
4235}
4236
4237void ArrayPatternNode::toString(StringBuilder& builder) const
4238{
4239 builder.append('[');
4240 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4241 const auto& target = m_targetPatterns[i];
4242
4243 switch (target.bindingType) {
4244 case BindingType::Elision:
4245 builder.append(',');
4246 break;
4247
4248 case BindingType::Element:
4249 target.pattern->toString(builder);
4250 if (i < m_targetPatterns.size() - 1)
4251 builder.append(',');
4252 break;
4253
4254 case BindingType::RestElement:
4255 builder.appendLiteral("...");
4256 target.pattern->toString(builder);
4257 break;
4258 }
4259 }
4260 builder.append(']');
4261}
4262
4263void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4264{
4265 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4266 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
4267 node->collectBoundIdentifiers(identifiers);
4268 }
4269}
4270
4271void ObjectPatternNode::toString(StringBuilder& builder) const
4272{
4273 builder.append('{');
4274 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4275 if (m_targetPatterns[i].wasString)
4276 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
4277 else
4278 builder.append(m_targetPatterns[i].propertyName.string());
4279 builder.append(':');
4280 m_targetPatterns[i].pattern->toString(builder);
4281 if (i < m_targetPatterns.size() - 1)
4282 builder.append(',');
4283 }
4284 builder.append('}');
4285}
4286
4287void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
4288{
4289 generator.emitRequireObjectCoercible(rhs, "Right side of assignment cannot be destructured"_s);
4290
4291 RefPtr<RegisterID> excludedList;
4292 IdentifierSet excludedSet;
4293 RefPtr<RegisterID> addMethod;
4294 if (m_containsRestElement && m_containsComputedProperty) {
4295 auto var = generator.variable(generator.propertyNames().builtinNames().SetPrivateName());
4296
4297 RefPtr<RegisterID> scope = generator.newTemporary();
4298 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
4299 RefPtr<RegisterID> setConstructor = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4300
4301 CallArguments args(generator, nullptr, 0);
4302 excludedList = generator.emitConstruct(generator.newTemporary(), setConstructor.get(), setConstructor.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
4303
4304 addMethod = generator.emitGetById(generator.newTemporary(), excludedList.get(), generator.propertyNames().builtinNames().addPrivateName());
4305 }
4306
4307 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4308 const auto& target = m_targetPatterns[i];
4309 if (target.bindingType == BindingType::Element) {
4310 RefPtr<RegisterID> temp = generator.newTemporary();
4311 RefPtr<RegisterID> propertyName;
4312 if (!target.propertyExpression) {
4313 Optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
4314 if (!optionalIndex)
4315 generator.emitGetById(temp.get(), rhs, target.propertyName);
4316 else {
4317 RefPtr<RegisterID> propertyIndex = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
4318 generator.emitGetByVal(temp.get(), rhs, propertyIndex.get());
4319 }
4320 } else {
4321 propertyName = generator.emitNodeForProperty(target.propertyExpression);
4322 generator.emitGetByVal(temp.get(), rhs, propertyName.get());
4323 }
4324
4325 if (m_containsRestElement) {
4326 if (m_containsComputedProperty) {
4327 if (!target.propertyExpression)
4328 propertyName = generator.emitLoad(nullptr, target.propertyName);
4329
4330 CallArguments args(generator, nullptr, 1);
4331 generator.move(args.thisRegister(), excludedList.get());
4332 generator.move(args.argumentRegister(0), propertyName.get());
4333 generator.emitCall(generator.newTemporary(), addMethod.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4334 } else
4335 excludedSet.add(target.propertyName.impl());
4336 }
4337
4338 if (target.defaultValue)
4339 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
4340 target.pattern->bindValue(generator, temp.get());
4341 } else {
4342 ASSERT(target.bindingType == BindingType::RestElement);
4343 ASSERT(i == m_targetPatterns.size() - 1);
4344 RefPtr<RegisterID> newObject = generator.emitNewObject(generator.newTemporary());
4345
4346 // load and call @copyDataProperties
4347 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
4348
4349 RefPtr<RegisterID> scope = generator.newTemporary();
4350 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
4351 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4352
4353 CallArguments args(generator, nullptr, 3);
4354 generator.emitLoad(args.thisRegister(), jsUndefined());
4355 generator.move(args.argumentRegister(0), newObject.get());
4356 generator.move(args.argumentRegister(1), rhs);
4357 if (m_containsComputedProperty)
4358 generator.move(args.argumentRegister(2), excludedList.get());
4359 else {
4360 RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
4361 generator.move(args.argumentRegister(2), excludedSetReg.get());
4362 }
4363
4364 RefPtr<RegisterID> result = generator.newTemporary();
4365 generator.emitCall(result.get(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4366 target.pattern->bindValue(generator, result.get());
4367 }
4368 }
4369}
4370
4371void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4372{
4373 for (size_t i = 0; i < m_targetPatterns.size(); i++)
4374 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
4375}
4376
4377void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
4378{
4379 Variable var = generator.variable(m_boundProperty);
4380 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
4381 if (RegisterID* local = var.local()) {
4382 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4383 generator.emitTDZCheckIfNecessary(var, local, nullptr);
4384 if (isReadOnly) {
4385 generator.emitReadOnlyExceptionIfNeeded(var);
4386 return;
4387 }
4388 generator.move(local, value);
4389 generator.emitProfileType(local, var, divotStart(), divotEnd());
4390 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
4391 generator.liftTDZCheckIfPossible(var);
4392 return;
4393 }
4394 if (generator.isStrictMode())
4395 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4396 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
4397 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4398 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4399 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
4400 if (isReadOnly) {
4401 generator.emitReadOnlyExceptionIfNeeded(var);
4402 return;
4403 }
4404 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
4405 generator.emitProfileType(value, var, divotStart(), divotEnd());
4406 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
4407 generator.liftTDZCheckIfPossible(var);
4408 return;
4409}
4410
4411void BindingNode::toString(StringBuilder& builder) const
4412{
4413 builder.append(m_boundProperty.string());
4414}
4415
4416void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4417{
4418 identifiers.append(m_boundProperty);
4419}
4420
4421void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
4422{
4423}
4424
4425void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
4426{
4427 if (m_assignmentTarget->isResolveNode()) {
4428 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
4429 Variable var = generator.variable(lhs->identifier());
4430 bool isReadOnly = var.isReadOnly();
4431 if (RegisterID* local = var.local()) {
4432 generator.emitTDZCheckIfNecessary(var, local, nullptr);
4433
4434 if (isReadOnly)
4435 generator.emitReadOnlyExceptionIfNeeded(var);
4436 else {
4437 generator.move(local, value);
4438 generator.emitProfileType(local, divotStart(), divotEnd());
4439 }
4440 return;
4441 }
4442 if (generator.isStrictMode())
4443 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4444 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
4445 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
4446 if (isReadOnly) {
4447 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
4448 if (threwException)
4449 return;
4450 }
4451 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4452 if (!isReadOnly) {
4453 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
4454 generator.emitProfileType(value, var, divotStart(), divotEnd());
4455 }
4456 } else if (m_assignmentTarget->isDotAccessorNode()) {
4457 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
4458 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4459 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4460 if (lhs->base()->isSuperNode()) {
4461 RefPtr<RegisterID> thisValue = generator.ensureThis();
4462 generator.emitPutById(base.get(), thisValue.get(), lhs->identifier(), value);
4463 } else
4464 generator.emitPutById(base.get(), lhs->identifier(), value);
4465 generator.emitProfileType(value, divotStart(), divotEnd());
4466 } else if (m_assignmentTarget->isBracketAccessorNode()) {
4467 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
4468 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4469 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(lhs->subscript(), true, false);
4470 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4471 if (lhs->base()->isSuperNode()) {
4472 RefPtr<RegisterID> thisValue = generator.ensureThis();
4473 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
4474 } else
4475 generator.emitPutByVal(base.get(), property.get(), value);
4476 generator.emitProfileType(value, divotStart(), divotEnd());
4477 }
4478}
4479
4480void AssignmentElementNode::toString(StringBuilder& builder) const
4481{
4482 if (m_assignmentTarget->isResolveNode())
4483 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
4484}
4485
4486void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4487{
4488 m_pattern->collectBoundIdentifiers(identifiers);
4489}
4490
4491void RestParameterNode::toString(StringBuilder& builder) const
4492{
4493 builder.appendLiteral("...");
4494 m_pattern->toString(builder);
4495}
4496
4497void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
4498{
4499 RELEASE_ASSERT_NOT_REACHED();
4500}
4501
4502void RestParameterNode::emit(BytecodeGenerator& generator)
4503{
4504 RefPtr<RegisterID> temp = generator.newTemporary();
4505 generator.emitRestParameter(temp.get(), m_numParametersToSkip);
4506 m_pattern->bindValue(generator, temp.get());
4507}
4508
4509
4510RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4511{
4512 RELEASE_ASSERT_NOT_REACHED();
4513 return 0;
4514}
4515
4516RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4517{
4518 RefPtr<RegisterID> src = generator.newTemporary();
4519 generator.emitNode(src.get(), m_expression);
4520
4521 // load and call @copyDataPropertiesNoExclusions
4522 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesNoExclusionsPrivateName());
4523
4524 RefPtr<RegisterID> scope = generator.newTemporary();
4525 generator.move(scope.get(), generator.emitResolveScope(scope.get(), var));
4526 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4527
4528 CallArguments args(generator, nullptr, 2);
4529 generator.emitLoad(args.thisRegister(), jsUndefined());
4530 generator.move(args.argumentRegister(0), dst);
4531 generator.move(args.argumentRegister(1), src.get());
4532
4533 generator.emitCall(generator.newTemporary(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4534
4535 return dst;
4536}
4537
4538} // namespace JSC
4539