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