blob: 6f39a1e894a875833449d3ebe870f4c43b0a34cd [file] [log] [blame]
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00004* Copyright (C) 2003-2017 Apple Inc. All rights reserved.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00005* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +00008 * Copyright (C) 2012 Igalia, S.L.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00009*
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"
oliver@apple.comd04e0a02014-02-01 01:37:59 +000029#include "NodeConstructors.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000030
oliver@apple.comc422ba02014-02-27 23:25:29 +000031#include "BuiltinNames.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000032#include "BytecodeGenerator.h"
33#include "CallFrame.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000034#include "JIT.h"
joepeck@webkit.org7e07f392016-09-22 18:59:47 +000035#include "JSCInlines.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000036#include "JSFunction.h"
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +000037#include "JSGeneratorFunction.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000038#include "JSGlobalObject.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000039#include "LabelScope.h"
40#include "Lexer.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000041#include "Parser.h"
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +000042#include "StackAlignment.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000043#include <wtf/Assertions.h>
mjs@apple.comaed3cef2009-12-09 01:29:52 +000044#include <wtf/Threading.h>
joepeck@webkit.org7e07f392016-09-22 18:59:47 +000045#include <wtf/text/StringBuilder.h>
mjs@apple.comaed3cef2009-12-09 01:29:52 +000046
47using namespace WTF;
48
49namespace JSC {
50
51/*
52 Details of the emitBytecode function.
53
54 Return value: The register holding the production's value.
55 dst: An optional parameter specifying the most efficient destination at
56 which to store the production's value. The callee must honor dst.
57
58 The dst argument provides for a crude form of copy propagation. For example,
59
60 x = 1
61
62 becomes
63
64 load r[x], 1
65
66 instead of
67
68 load r0, 1
69 mov r[x], r0
70
71 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
72*/
73
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +000074void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +000075{
76 RegisterID* result = generator.emitNode(this);
77 if (fallThroughMode == FallThroughMeansTrue)
78 generator.emitJumpIfFalse(result, falseTarget);
79 else
80 generator.emitJumpIfTrue(result, trueTarget);
81}
82
mjs@apple.comaed3cef2009-12-09 01:29:52 +000083// ------------------------------ ThrowableExpressionData --------------------------------
84
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000085RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000086{
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +000087 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com4920ae92010-11-12 03:06:07 +000088 generator.emitThrowReferenceError(message);
89 return generator.newTemporary();
mjs@apple.comaed3cef2009-12-09 01:29:52 +000090}
91
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000092// ------------------------------ ConstantNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +000093
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +000094void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000095{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000096 TriState value = jsValue(generator).pureToBoolean();
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +000097
98 if (UNLIKELY(needsDebugHook())) {
99 if (value != MixedTriState)
100 generator.emitDebugHook(this);
101 }
102
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000103 if (value == MixedTriState)
104 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
105 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
106 generator.emitJump(trueTarget);
107 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
108 generator.emitJump(falseTarget);
109
110 // All other cases are unconditional fall-throughs, like "if (true)".
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000111}
112
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000113RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000114{
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000115 if (dst == generator.ignoredResult())
116 return 0;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000117 return generator.emitLoad(dst, jsValue(generator));
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000118}
119
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000120JSValue StringNode::jsValue(BytecodeGenerator& generator) const
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000121{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000122 return generator.addStringConstant(m_value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000123}
124
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000125// ------------------------------ NumberNode ----------------------------------
126
127RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
128{
129 if (dst == generator.ignoredResult())
130 return nullptr;
131 return generator.emitLoad(dst, jsValue(generator), isIntegerNode() ? SourceCodeRepresentation::Integer : SourceCodeRepresentation::Double);
132}
133
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000134// ------------------------------ RegExpNode -----------------------------------
135
136RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
137{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000138 if (dst == generator.ignoredResult())
139 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000140 return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string())));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000141}
142
143// ------------------------------ ThisNode -------------------------------------
144
145RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
146{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000147 generator.ensureThis();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000148 if (dst == generator.ignoredResult())
149 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000150
151 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000152 static const unsigned thisLength = 4;
153 generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000154 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000155}
156
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000157// ------------------------------ SuperNode -------------------------------------
158
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000159static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000160{
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000161 if (generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {
162 RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000163 return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().builtinNames().homeObjectPrivateName());
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000164 }
165
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000166 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000167 callee.setIndex(CallFrameSlot::callee);
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000168 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().builtinNames().homeObjectPrivateName());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000169}
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000170
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000171static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
172{
173 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000174 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
175}
176
sbarati@apple.com23315d62016-05-09 20:17:23 +0000177static RegisterID* emitGetSuperFunctionForConstruct(BytecodeGenerator& generator)
178{
179 if (generator.isDerivedConstructorContext())
180 return generator.emitGetById(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(), generator.propertyNames().underscoreProto);
181
182 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000183 callee.setIndex(CallFrameSlot::callee);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000184 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().underscoreProto);
185}
186
187RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
188{
189 RegisterID* result = emitSuperBaseForCallee(generator);
190 return generator.moveToDestinationIfNeeded(generator.finalDestination(dst), result);
191}
192
utatane.tea@gmail.com5e639122017-01-09 22:02:47 +0000193// ------------------------------ ImportNode -------------------------------------
194
195RegisterID* ImportNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
196{
197 RefPtr<RegisterID> importModule = generator.emitGetGlobalPrivate(generator.newTemporary(), generator.propertyNames().builtinNames().importModulePrivateName());
198 CallArguments arguments(generator, nullptr, 1);
199 generator.emitLoad(arguments.thisRegister(), jsUndefined());
200 generator.emitNode(arguments.argumentRegister(0), m_expr);
201 return generator.emitCall(generator.finalDestination(dst, importModule.get()), importModule.get(), NoExpectedFunction, arguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
202}
203
commit-queue@webkit.org17f99e42015-07-21 18:18:42 +0000204// ------------------------------ NewTargetNode ----------------------------------
205
206RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
207{
208 if (dst == generator.ignoredResult())
209 return nullptr;
210
211 return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
212}
213
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000214// ------------------------------ ResolveNode ----------------------------------
215
216bool ResolveNode::isPure(BytecodeGenerator& generator) const
217{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000218 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000219}
220
221RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
222{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000223 Variable var = generator.variable(m_ident);
224 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000225 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000226 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000227 return nullptr;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000228
229 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000230 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000231 }
232
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000233 JSTextPosition divot = m_start + m_ident.length();
234 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000235 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000236 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000237 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000238 generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000239 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000240 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000241}
242
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000243// ------------------------------ TemplateStringNode -----------------------------------
244
245RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
246{
247 if (dst == generator.ignoredResult())
248 return nullptr;
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000249 ASSERT(cooked());
250 return generator.emitLoad(dst, JSValue(generator.addStringConstant(*cooked())));
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000251}
252
253// ------------------------------ TemplateLiteralNode -----------------------------------
254
255RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
256{
257 if (!m_templateExpressions) {
258 TemplateStringNode* templateString = m_templateStrings->value();
259 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
260 return generator.emitNode(dst, templateString);
261 }
262
263 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
264
265 TemplateStringListNode* templateString = m_templateStrings;
266 TemplateExpressionListNode* templateExpression = m_templateExpressions;
267 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
268 // Evaluate TemplateString.
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000269 ASSERT(templateString->value()->cooked());
270 if (!templateString->value()->cooked()->isEmpty()) {
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000271 temporaryRegisters.append(generator.newTemporary());
272 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
273 }
274
275 // Evaluate Expression.
276 temporaryRegisters.append(generator.newTemporary());
277 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
278 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
279 }
280
281 // Evaluate tail TemplateString.
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000282 ASSERT(templateString->value()->cooked());
283 if (!templateString->value()->cooked()->isEmpty()) {
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000284 temporaryRegisters.append(generator.newTemporary());
285 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
286 }
287
oliver@apple.com1aec7c72016-06-13 23:17:00 +0000288 if (temporaryRegisters.size() == 1)
289 return generator.emitToString(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get());
290
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000291 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
292}
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000293
294// ------------------------------ TaggedTemplateNode -----------------------------------
295
296RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
297{
298 ExpectedFunction expectedFunction = NoExpectedFunction;
299 RefPtr<RegisterID> tag = nullptr;
300 RefPtr<RegisterID> base = nullptr;
301 if (!m_tag->isLocation()) {
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000302 tag = generator.newTemporary();
303 tag = generator.emitNode(tag.get(), m_tag);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000304 } else if (m_tag->isResolveNode()) {
305 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
306 const Identifier& identifier = resolve->identifier();
307 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
308
309 Variable var = generator.variable(identifier);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000310 if (RegisterID* local = var.local()) {
311 generator.emitTDZCheckIfNecessary(var, local, nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000312 tag = generator.emitMove(generator.newTemporary(), local);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000313 } else {
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000314 tag = generator.newTemporary();
315 base = generator.newTemporary();
316
317 JSTextPosition newDivot = divotStart() + identifier.length();
318 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
319 generator.moveToDestinationIfNeeded(base.get(), generator.emitResolveScope(base.get(), var));
320 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000321 generator.emitTDZCheckIfNecessary(var, tag.get(), nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000322 }
323 } else if (m_tag->isBracketAccessorNode()) {
324 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000325 base = generator.newTemporary();
326 base = generator.emitNode(base.get(), bracket->base());
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +0000327 RefPtr<RegisterID> property = generator.emitNodeForProperty(bracket->subscript());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000328 if (bracket->base()->isSuperNode()) {
329 RefPtr<RegisterID> thisValue = generator.ensureThis();
330 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
331 } else
332 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000333 } else {
334 ASSERT(m_tag->isDotAccessorNode());
335 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000336 base = generator.newTemporary();
337 base = generator.emitNode(base.get(), dot->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000338 if (dot->base()->isSuperNode()) {
339 RefPtr<RegisterID> thisValue = generator.ensureThis();
340 tag = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), dot->identifier());
341 } else
342 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000343 }
344
utatane.tea@gmail.com6cd55812017-04-05 07:09:41 +0000345 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(nullptr, this);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000346
347 unsigned expressionsCount = 0;
348 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
349 ++expressionsCount;
350
351 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
352 if (base)
353 generator.emitMove(callArguments.thisRegister(), base.get());
354 else
355 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
356
357 unsigned argumentIndex = 0;
358 generator.emitMove(callArguments.argumentRegister(argumentIndex++), templateObject.get());
359 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
360 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
361
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000362 return generator.emitCallInTailPosition(generator.finalDestination(dst, tag.get()), tag.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000363}
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000364
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000365// ------------------------------ ArrayNode ------------------------------------
366
367RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
368{
369 // FIXME: Should we put all of this code into emitNewArray?
370
371 unsigned length = 0;
372 ElementNode* firstPutElement;
373 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000374 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000375 break;
376 ++length;
377 }
378
379 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000380 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000381
sbarati@apple.com99ed4792016-11-12 02:58:11 +0000382 if (firstPutElement && firstPutElement->value()->isSpreadExpression()) {
383 bool hasElision = false;
384 for (ElementNode* node = m_element; node; node = node->next()) {
385 if (!!node->elision()) {
386 hasElision = true;
387 break;
388 }
389 }
390 if (!!m_elision)
391 hasElision = true;
392
393 if (!hasElision)
394 return generator.emitNewArrayWithSpread(generator.finalDestination(dst), m_element);
395 }
396
oliver@apple.coma991d692011-06-14 23:39:25 +0000397 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000398 ElementNode* n = firstPutElement;
399 for (; n; n = n->next()) {
400 if (n->value()->isSpreadExpression())
401 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000402 RegisterID* value = generator.emitNode(n->value());
403 length += n->elision();
404 generator.emitPutByIndex(array.get(), length++, value);
405 }
406
407 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000408 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000409 generator.emitPutById(array.get(), generator.propertyNames().length, value);
410 }
411
412 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000413
414handleSpread:
415 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
annulen@yandex.ru0226e412017-04-21 03:38:16 +0000416 auto spreader = [array, index](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com72f8a822013-10-17 01:02:34 +0000417 {
oliver@apple.come050d642013-10-19 00:09:28 +0000418 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000419 generator.emitInc(index.get());
420 };
421 for (; n; n = n->next()) {
422 if (n->elision())
423 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
424 if (n->value()->isSpreadExpression()) {
425 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
426 generator.emitEnumeration(spread, spread->expression(), spreader);
427 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000428 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000429 generator.emitInc(index.get());
430 }
431 }
432
433 if (m_elision) {
434 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
435 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
436 }
437 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000438}
439
440bool ArrayNode::isSimpleArray() const
441{
442 if (m_elision || m_optional)
443 return false;
444 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
445 if (ptr->elision())
446 return false;
commit-queue@webkit.org1a78b432016-09-15 01:14:45 +0000447 if (ptr->value()->isSpreadExpression())
448 return false;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000449 }
450 return true;
451}
452
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000453ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000454{
455 ASSERT(!m_elision && !m_optional);
456 ElementNode* ptr = m_element;
457 if (!ptr)
458 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000459 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000460 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000461 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000462 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000463 ArgumentListNode* tail = head;
464 ptr = ptr->next();
465 for (; ptr; ptr = ptr->next()) {
466 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000467 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000468 }
469 return head;
470}
471
472// ------------------------------ ObjectLiteralNode ----------------------------
473
474RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
475{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000476 if (!m_list) {
477 if (dst == generator.ignoredResult())
478 return 0;
479 return generator.emitNewObject(generator.finalDestination(dst));
480 }
481 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
482 generator.emitNode(newObj.get(), m_list);
483 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000484}
485
486// ------------------------------ PropertyListNode -----------------------------
487
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000488static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
489{
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000490 generator.emitPutById(function, generator.propertyNames().builtinNames().homeObjectPrivateName(), homeObject);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000491}
492
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000493RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
494{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000495 // Fast case: this loop just handles regular value properties.
496 PropertyListNode* p = this;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000497 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000498 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000499
500 // Were there any get/set properties?
501 if (p) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000502 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
ticaiolima@gmail.comf62044c2017-07-13 07:11:45 +0000503 // a computed property or a spread, just emit everything as that may override previous values.
504 bool canOverrideProperties = false;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000505
barraclough@apple.com09a55682012-01-30 18:28:39 +0000506 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000507 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000508 GetterSetterMap map;
509
510 // Build a map, pairing get/set values together.
511 for (PropertyListNode* q = p; q; q = q->m_next) {
512 PropertyNode* node = q->m_node;
ticaiolima@gmail.comf62044c2017-07-13 07:11:45 +0000513 if (node->m_type & PropertyNode::Computed || node->m_type & PropertyNode::Spread) {
514 canOverrideProperties = true;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000515 break;
516 }
ticaiolima@gmail.comf62044c2017-07-13 07:11:45 +0000517
mark.lam@apple.comcf0bf6c2017-05-16 00:21:59 +0000518 if (node->m_type & PropertyNode::Constant)
barraclough@apple.com09a55682012-01-30 18:28:39 +0000519 continue;
520
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000521 // Duplicates are possible.
522 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
oliver@apple.com72d38322013-10-21 19:23:24 +0000523 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000524 if (!result.isNewEntry) {
525 if (result.iterator->value.first->m_type == node->m_type)
526 result.iterator->value.first = node;
527 else
528 result.iterator->value.second = node;
529 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000530 }
531
532 // Iterate over the remaining properties in the list.
533 for (; p; p = p->m_next) {
534 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000535
536 // Handle regular values.
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000537 if (node->m_type & PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000538 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000539 continue;
ticaiolima@gmail.comf62044c2017-07-13 07:11:45 +0000540 } else if (node->m_type & PropertyNode::Spread) {
541 generator.emitNode(dst, node->m_assign);
542 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000543 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000544
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000545 RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000546 bool needsSuperBinding = node->needsSuperBinding();
547 if (needsSuperBinding)
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000548 emitPutHomeObject(generator, value.get(), dst);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000549
550 unsigned attributes = node->isClassProperty() ? (Accessor | DontEnum) : Accessor;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000551
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000552 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
553
ticaiolima@gmail.comf62044c2017-07-13 07:11:45 +0000554 // This is a get/set property which may be overridden by a computed property or spread later.
555 if (canOverrideProperties) {
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000556 // Computed accessors.
557 if (node->m_type & PropertyNode::Computed) {
558 RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000559 generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000560 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000561 generator.emitPutGetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000562 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000563 generator.emitPutSetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000564 continue;
565 }
566
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000567 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000568 generator.emitPutGetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000569 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000570 generator.emitPutSetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000571 continue;
572 }
573
574 // This is a get/set property pair.
oliver@apple.com72d38322013-10-21 19:23:24 +0000575 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000576 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000577 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000578
579 // Was this already generated as a part of its partner?
580 if (pair.second == node)
581 continue;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000582
barraclough@apple.com09a55682012-01-30 18:28:39 +0000583 // Generate the paired node now.
584 RefPtr<RegisterID> getterReg;
585 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000586 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000587
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000588 if (node->m_type & PropertyNode::Getter) {
barraclough@apple.com09a55682012-01-30 18:28:39 +0000589 getterReg = value;
590 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000591 ASSERT(pair.second->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000592 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000593 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000594 } else {
595 setterReg = generator.newTemporary();
596 generator.emitLoad(setterReg.get(), jsUndefined());
597 }
598 } else {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000599 ASSERT(node->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000600 setterReg = value;
601 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000602 ASSERT(pair.second->m_type & PropertyNode::Getter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000603 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000604 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000605 } else {
606 getterReg = generator.newTemporary();
607 generator.emitLoad(getterReg.get(), jsUndefined());
608 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000609 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000610
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000611 ASSERT(!pair.second || needsSuperBinding == pair.second->needsSuperBinding());
612 if (needsSuperBinding && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000613 emitPutHomeObject(generator, secondReg, dst);
614
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000615 generator.emitPutGetterSetter(dst, *node->name(), attributes, getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000616 }
617 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000618
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000619 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000620}
621
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000622void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
623{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000624 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000625 if (node.needsSuperBinding())
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000626 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000627
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000628 if (node.isClassProperty()) {
629 ASSERT(node.needsSuperBinding());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000630 RefPtr<RegisterID> propertyNameRegister;
631 if (node.name())
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000632 propertyNameRegister = generator.emitLoad(nullptr, *node.name());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000633 else
634 propertyNameRegister = generator.emitNode(node.m_expression);
635
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000636 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +0000637 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000638 return;
639 }
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000640 if (const auto* identifier = node.name()) {
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000641 std::optional<uint32_t> optionalIndex = parseIndex(*identifier);
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000642 if (!optionalIndex) {
643 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
644 return;
645 }
646
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000647 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000648 generator.emitDirectPutByVal(newObj, index.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000649 return;
650 }
651 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000652 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000653 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000654}
655
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000656// ------------------------------ BracketAccessorNode --------------------------------
657
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000658static bool isNonIndexStringElement(ExpressionNode& element)
659{
660 return element.isString() && !parseIndex(static_cast<StringNode&>(element).value());
661}
662
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000663RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
664{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000665 if (m_base->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000666 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
667 RefPtr<RegisterID> thisValue = generator.ensureThis();
668 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000669
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000670 if (isNonIndexStringElement(*m_subscript)) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000671 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000672 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000673 generator.emitGetById(finalDest.get(), superBase.get(), thisValue.get(), id);
674 } else {
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +0000675 RefPtr<RegisterID> subscript = generator.emitNodeForProperty(m_subscript);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000676 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000677 generator.emitGetByVal(finalDest.get(), superBase.get(), thisValue.get(), subscript.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000678 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000679
sbarati@apple.com23315d62016-05-09 20:17:23 +0000680 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
681 return finalDest.get();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000682 }
683
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000684 RegisterID* ret;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000685 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000686
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000687 if (isNonIndexStringElement(*m_subscript)) {
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000688 RefPtr<RegisterID> base = generator.emitNode(m_base);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000689 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000690 ret = generator.emitGetById(finalDest.get(), base.get(), static_cast<StringNode*>(m_subscript)->value());
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000691 } else {
692 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +0000693 RegisterID* property = generator.emitNodeForProperty(m_subscript);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000694 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000695 ret = generator.emitGetByVal(finalDest.get(), base.get(), property);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000696 }
697
sbarati@apple.com23315d62016-05-09 20:17:23 +0000698 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000699 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000700}
701
702// ------------------------------ DotAccessorNode --------------------------------
703
704RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
705{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000706 bool baseIsSuper = m_base->isSuperNode();
707 RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000708 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000709 RegisterID* finalDest = generator.finalDestination(dst);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000710 RegisterID* ret;
711 if (baseIsSuper) {
712 RefPtr<RegisterID> thisValue = generator.ensureThis();
713 ret = generator.emitGetById(finalDest, base.get(), thisValue.get(), m_ident);
714 } else
715 ret = generator.emitGetById(finalDest, base.get(), m_ident);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000716 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000717 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000718}
719
720// ------------------------------ ArgumentListNode -----------------------------
721
722RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
723{
724 ASSERT(m_expr);
725 return generator.emitNode(dst, m_expr);
726}
727
728// ------------------------------ NewExprNode ----------------------------------
729
730RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
731{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000732 ExpectedFunction expectedFunction;
733 if (m_expr->isResolveNode())
734 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
735 else
736 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000737 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000738 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000739 CallArguments callArguments(generator, m_args);
fpizlo@apple.com42125692017-05-18 19:55:01 +0000740 return generator.emitConstruct(returnValue.get(), func.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000741}
742
oliver@apple.com72f8a822013-10-17 01:02:34 +0000743CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000744 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000745 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000746{
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000747 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000748 if (argumentsNode) {
749 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
750 ++argumentCountIncludingThis;
751 }
752
753 m_argv.grow(argumentCountIncludingThis);
754 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
755 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000756 ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() - 1);
ggaren@apple.com0af14682011-12-12 00:35:51 +0000757 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000758
759 // We need to ensure that the frame size is stack-aligned
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000760 while ((CallFrame::headerSizeInRegisters + m_argv.size()) % stackAlignmentRegisters()) {
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000761 m_argv.insert(0, generator.newTemporary());
762 m_padding++;
763 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000764
765 while (stackOffset() % stackAlignmentRegisters()) {
766 m_argv.insert(0, generator.newTemporary());
767 m_padding++;
768 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000769}
770
771// ------------------------------ EvalFunctionCallNode ----------------------------------
772
773RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
774{
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000775 // We need try to load 'this' before call eval in constructor, because 'this' can created by 'super' in some of the arrow function
776 // var A = class A {
777 // constructor () { this.id = 'A'; }
778 // }
779 //
780 // var B = class B extend A {
781 // constructor () {
782 // var arrow = () => super();
783 // arrow();
784 // eval("this.id = 'B'");
785 // }
786 // }
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000787 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000788 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
789
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000790 Variable var = generator.variable(generator.propertyNames().eval);
791 if (RegisterID* local = var.local()) {
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000792 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000793 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000794 CallArguments callArguments(generator, m_args);
795 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000796 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
oliver@apple.com58c86752013-07-25 04:02:40 +0000797 }
798
799 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000800 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000801 JSTextPosition newDivot = divotStart() + 4;
802 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000803 generator.moveToDestinationIfNeeded(
804 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000805 generator.emitResolveScope(callArguments.thisRegister(), var));
806 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000807 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000808 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000809}
810
811// ------------------------------ FunctionCallValueNode ----------------------------------
812
813RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
814{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000815 if (m_expr->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000816 RefPtr<RegisterID> func = emitGetSuperFunctionForConstruct(generator);
817 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
818 CallArguments callArguments(generator, m_args);
819
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000820 ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000821 ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
fpizlo@apple.com42125692017-05-18 19:55:01 +0000822 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), generator.newTarget(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000823
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000824 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000825 bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
826
827 if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction()))
828 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
829
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +0000830 Ref<Label> thisIsEmptyLabel = generator.newLabel();
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000831 generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get());
832 generator.emitThrowReferenceError(ASCIILiteral("'super()' can't be called more than once in a constructor."));
833 generator.emitLabel(thisIsEmptyLabel.get());
834
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000835 generator.emitMove(generator.thisRegister(), ret);
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000836
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000837 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor)
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000838 generator.emitPutThisToArrowFunctionContextScope();
commit-queue@webkit.orgabdc6172016-02-24 20:46:44 +0000839
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000840 return ret;
841 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000842 RefPtr<RegisterID> func = generator.emitNode(m_expr);
843 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
844 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000845 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000846 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000847 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000848 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000849}
850
851// ------------------------------ FunctionCallResolveNode ----------------------------------
852
853RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
854{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000855 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000856
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000857 Variable var = generator.variable(m_ident);
858 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000859 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000860 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000861 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000862 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000863 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000864 // This passes NoExpectedFunction because we expect that if the function is in a
865 // local variable, then it's not one of our built-in constructors.
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000866 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000867 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000868 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000869 }
870
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000871 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000872 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000873 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000874
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000875 JSTextPosition newDivot = divotStart() + m_ident.length();
876 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000877 generator.moveToDestinationIfNeeded(
878 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000879 generator.emitResolveScope(callArguments.thisRegister(), var));
880 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000881 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000882 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000883 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000884 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000885}
886
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000887// ------------------------------ BytecodeIntrinsicNode ----------------------------------
888
889RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
890{
891 return (this->*m_emitter)(generator, dst);
892}
893
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +0000894RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argument(BytecodeGenerator& generator, RegisterID* dst)
895{
896 ArgumentListNode* node = m_args->m_listNode;
897 ASSERT(node->m_expr->isNumber());
898 double value = static_cast<NumberNode*>(node->m_expr)->value();
899 int32_t index = static_cast<int32_t>(value);
900 ASSERT(value == index);
901 ASSERT(index >= 0);
902 ASSERT(!node->m_next);
903
904 // The body functions of generator and async have different mechanism for arguments.
905 ASSERT(generator.parseMode() != SourceParseMode::GeneratorBodyMode);
906 ASSERT(!isAsyncFunctionBodyParseMode(generator.parseMode()));
907
908 return generator.emitGetArgument(generator.finalDestination(dst), index);
909}
910
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +0000911RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator& generator, RegisterID* dst)
912{
913 ASSERT(!m_args->m_listNode);
914
915 return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
916}
917
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +0000918RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator& generator, RegisterID* dst)
919{
920#ifndef NDEBUG
921 ArgumentListNode* node = m_args->m_listNode;
922 RefPtr<RegisterID> condition = generator.emitNode(node);
923 generator.emitAssert(condition.get(), node->firstLine());
924 return dst;
925#else
926 UNUSED_PARAM(generator);
927 return dst;
928#endif
929}
930
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000931RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
932{
933 ArgumentListNode* node = m_args->m_listNode;
934 RefPtr<RegisterID> base = generator.emitNode(node);
935 node = node->m_next;
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +0000936 RefPtr<RegisterID> index = generator.emitNodeForProperty(node);
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000937 node = node->m_next;
938 RefPtr<RegisterID> value = generator.emitNode(node);
939
940 ASSERT(!node->m_next);
941
942 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
943}
944
keith_miller@apple.come497e202016-06-13 21:05:36 +0000945RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator& generator, RegisterID* dst)
946{
947 ArgumentListNode* node = m_args->m_listNode;
948 RefPtr<RegisterID> function = generator.emitNode(node);
949 node = node->m_next;
950 RefPtr<RegisterID> thisRegister = generator.emitNode(node);
951 ASSERT(!node->m_next);
952
953 RefPtr<RegisterID> finalDst = generator.finalDestination(dst);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000954 return generator.emitCallForwardArgumentsInTailPosition(finalDst.get(), function.get(), thisRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd(), DebuggableCall::No);
keith_miller@apple.come497e202016-06-13 21:05:36 +0000955}
956
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000957RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwTypeError(BytecodeGenerator& generator, RegisterID* dst)
958{
959 ArgumentListNode* node = m_args->m_listNode;
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000960 ASSERT(!node->m_next);
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +0000961 if (node->m_expr->isString()) {
962 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
963 generator.emitThrowTypeError(ident);
964 } else {
965 RefPtr<RegisterID> message = generator.emitNode(node);
966 generator.emitThrowStaticError(ErrorType::TypeError, message.get());
967 }
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000968 return dst;
969}
970
971RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwRangeError(BytecodeGenerator& generator, RegisterID* dst)
972{
973 ArgumentListNode* node = m_args->m_listNode;
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000974 ASSERT(!node->m_next);
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +0000975 if (node->m_expr->isString()) {
976 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
977 generator.emitThrowRangeError(ident);
978 } else {
979 RefPtr<RegisterID> message = generator.emitNode(node);
980 generator.emitThrowStaticError(ErrorType::RangeError, message.get());
981 }
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000982
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000983 return dst;
984}
985
986RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwOutOfMemoryError(BytecodeGenerator& generator, RegisterID* dst)
987{
988 ASSERT(!m_args->m_listNode);
989
990 generator.emitThrowOutOfMemoryError();
991 return dst;
992}
993
keith_miller@apple.com8844d302016-04-07 19:38:00 +0000994RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
995{
996 ArgumentListNode* node = m_args->m_listNode;
997 RefPtr<RegisterID> base = generator.emitNode(node);
998 node = node->m_next;
999
1000 // Since this is a builtin we expect the creator to use a string literal as the second argument.
1001 ASSERT(node->m_expr->isString());
1002 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1003 ASSERT(!node->m_next);
1004
keith_miller@apple.come497e202016-06-13 21:05:36 +00001005 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
1006 return generator.emitTryGetById(finalDest.get(), base.get(), ident);
keith_miller@apple.com8844d302016-04-07 19:38:00 +00001007}
1008
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001009RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toNumber(BytecodeGenerator& generator, RegisterID* dst)
1010{
1011 ArgumentListNode* node = m_args->m_listNode;
1012 RefPtr<RegisterID> src = generator.emitNode(node);
1013 ASSERT(!node->m_next);
1014
1015 return generator.moveToDestinationIfNeeded(dst, generator.emitToNumber(generator.tempDestination(dst), src.get()));
1016}
1017
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +00001018RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
1019{
1020 ArgumentListNode* node = m_args->m_listNode;
1021 RefPtr<RegisterID> src = generator.emitNode(node);
1022 ASSERT(!node->m_next);
1023
1024 return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
1025}
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001026
1027RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isJSArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1028{
1029 ArgumentListNode* node = m_args->m_listNode;
1030 RefPtr<RegisterID> src = generator.emitNode(node);
1031 ASSERT(!node->m_next);
1032
1033 return generator.moveToDestinationIfNeeded(dst, generator.emitIsJSArray(generator.tempDestination(dst), src.get()));
1034}
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +00001035
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001036RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1037{
1038 ArgumentListNode* node = m_args->m_listNode;
1039 RefPtr<RegisterID> src = generator.emitNode(node);
1040 ASSERT(!node->m_next);
1041
1042 return generator.moveToDestinationIfNeeded(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
1043}
1044
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +00001045RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1046{
1047 ArgumentListNode* node = m_args->m_listNode;
1048 RefPtr<RegisterID> src = generator.emitNode(node);
1049 ASSERT(!node->m_next);
1050
1051 return generator.moveToDestinationIfNeeded(dst, generator.emitIsRegExpObject(generator.tempDestination(dst), src.get()));
1052}
1053
utatane.tea@gmail.com0f56f572016-02-08 23:14:47 +00001054RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
1055{
1056 ArgumentListNode* node = m_args->m_listNode;
1057 RefPtr<RegisterID> src = generator.emitNode(node);
1058 ASSERT(!node->m_next);
1059
1060 return generator.moveToDestinationIfNeeded(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
1061}
1062
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001063RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1064{
1065 ArgumentListNode* node = m_args->m_listNode;
1066 RefPtr<RegisterID> src = generator.emitNode(node);
1067 ASSERT(!node->m_next);
1068
1069 return generator.moveToDestinationIfNeeded(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
1070}
1071
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +00001072RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isMap(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1073{
1074 ArgumentListNode* node = m_args->m_listNode;
1075 RefPtr<RegisterID> src = generator.emitNode(node);
1076 ASSERT(!node->m_next);
1077
1078 return generator.moveToDestinationIfNeeded(dst, generator.emitIsMap(generator.tempDestination(dst), src.get()));
1079}
1080
1081RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isSet(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1082{
1083 ArgumentListNode* node = m_args->m_listNode;
1084 RefPtr<RegisterID> src = generator.emitNode(node);
1085 ASSERT(!node->m_next);
1086
1087 return generator.moveToDestinationIfNeeded(dst, generator.emitIsSet(generator.tempDestination(dst), src.get()));
1088}
1089
sbarati@apple.com3cc67a72016-08-18 17:17:41 +00001090RegisterID* BytecodeIntrinsicNode::emit_intrinsic_newArrayWithSize(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1091{
1092 ArgumentListNode* node = m_args->m_listNode;
1093 RefPtr<RegisterID> size = generator.emitNode(node);
1094 ASSERT(!node->m_next);
1095
1096 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst);
1097 generator.emitNewArrayWithSize(finalDestination.get(), size.get());
1098 return finalDestination.get();
1099}
1100
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +00001101RegisterID* BytecodeIntrinsicNode::emit_intrinsic_defineEnumerableWritableConfigurableDataProperty(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1102{
1103 ArgumentListNode* node = m_args->m_listNode;
1104 RefPtr<RegisterID> newObj = generator.emitNode(node);
1105 node = node->m_next;
1106 RefPtr<RegisterID> propertyNameRegister = generator.emitNode(node);
1107 node = node->m_next;
1108 RefPtr<RegisterID> value = generator.emitNode(node);
1109 ASSERT(!node->m_next);
1110
1111 generator.emitCallDefineProperty(newObj.get(), propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable | BytecodeGenerator::PropertyEnumerable, m_position);
1112 return dst;
1113}
utatane.tea@gmail.combf8978b2016-02-02 19:33:05 +00001114
1115#define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \
1116 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_##name(BytecodeGenerator& generator, RegisterID* dst) \
1117 { \
1118 ASSERT(!m_args); \
1119 ASSERT(type() == Type::Constant); \
1120 if (dst == generator.ignoredResult()) \
1121 return nullptr; \
1122 return generator.emitLoad(dst, generator.vm()->bytecodeIntrinsicRegistry().name##Value(generator)); \
1123 }
1124 JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
1125#undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
1126
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001127// ------------------------------ FunctionCallBracketNode ----------------------------------
1128
1129RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1130{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001131 bool baseIsSuper = m_base->isSuperNode();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001132 bool subscriptIsNonIndexString = isNonIndexStringElement(*m_subscript);
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001133
1134 RefPtr<RegisterID> base;
1135 if (baseIsSuper)
1136 base = emitSuperBaseForCallee(generator);
1137 else {
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001138 if (subscriptIsNonIndexString)
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001139 base = generator.emitNode(m_base);
1140 else
1141 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
1142 }
1143
1144 RefPtr<RegisterID> function;
sbarati@apple.com23315d62016-05-09 20:17:23 +00001145 RefPtr<RegisterID> thisRegister;
1146 if (baseIsSuper) {
1147 // 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.
1148 thisRegister = generator.ensureThis();
1149 }
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001150 if (subscriptIsNonIndexString) {
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001151 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001152 if (baseIsSuper)
1153 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisRegister.get(), static_cast<StringNode*>(m_subscript)->value());
1154 else
1155 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001156 } else {
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00001157 RefPtr<RegisterID> property = generator.emitNodeForProperty(m_subscript);
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001158 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001159 if (baseIsSuper)
1160 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisRegister.get(), property.get());
1161 else
1162 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001163 }
1164
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001165 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001166 CallArguments callArguments(generator, m_args);
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001167 if (baseIsSuper) {
1168 generator.emitTDZCheck(generator.thisRegister());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001169 generator.emitMove(callArguments.thisRegister(), thisRegister.get());
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001170 } else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001171 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001172 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001173 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001174 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001175}
1176
1177// ------------------------------ FunctionCallDotNode ----------------------------------
1178
1179RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1180{
1181 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001182 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001183 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001184 bool baseIsSuper = m_base->isSuperNode();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001185 if (baseIsSuper)
1186 generator.emitMove(callArguments.thisRegister(), generator.ensureThis());
1187 else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001188 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001189 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001190 if (baseIsSuper) {
1191 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
1192 generator.emitGetById(function.get(), superBase.get(), callArguments.thisRegister(), m_ident);
1193 } else
1194 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001195 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001196 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001197 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001198}
1199
sbarati@apple.com4ddd2ec2017-05-04 12:20:59 +00001200static constexpr size_t maxDistanceToInnermostCallOrApply = 2;
sbarati@apple.com07f9fa92017-04-18 19:02:01 +00001201
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001202RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1203{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001204 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001205 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001206 RefPtr<RegisterID> function;
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001207 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
1208
1209 auto makeFunction = [&] {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001210 if (m_base->isSuperNode()) {
1211 RefPtr<RegisterID> thisValue = generator.ensureThis();
1212 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().callPublicName());
1213 } else
1214 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001215 };
1216
1217 bool emitCallCheck = !generator.isBuiltinFunction();
sbarati@apple.com07f9fa92017-04-18 19:02:01 +00001218 if (m_distanceToInnermostCallOrApply > maxDistanceToInnermostCallOrApply && emitCallCheck) {
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001219 makeFunction();
1220 CallArguments callArguments(generator, m_args);
1221 generator.emitMove(callArguments.thisRegister(), base.get());
1222 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1223 generator.moveToDestinationIfNeeded(dst, returnValue.get());
1224 return returnValue.get();
1225 }
1226
1227 Ref<Label> realCall = generator.newLabel();
1228 Ref<Label> end = generator.newLabel();
1229
1230 if (emitCallCheck) {
1231 makeFunction();
oliver@apple.comba848d12014-02-12 17:14:23 +00001232 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001233 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001234 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001235 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001236 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
1237 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001238 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001239 argumentsRegister = generator.emitNode(subject);
1240 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
1241 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001242 generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001243 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001244 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001245 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +00001246
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001247 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1248 CallArguments callArguments(generator, m_args);
1249 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001250 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001251 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001252 } else {
1253 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1254 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +00001255 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001256 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001257 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001258 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001259 if (emitCallCheck) {
1260 generator.emitJump(end.get());
1261 generator.emitLabel(realCall.get());
1262 {
1263 CallArguments callArguments(generator, m_args);
1264 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001265 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001266 }
1267 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001268 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001269 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001270 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001271}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001272
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001273static bool areTrivialApplyArguments(ArgumentsNode* args)
1274{
1275 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
1276 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
1277}
1278
1279RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1280{
1281 // A few simple cases can be trivially handled as ordinary function calls.
1282 // function.apply(), function.apply(arg) -> identical to function.call
1283 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
1284 bool mayBeCall = areTrivialApplyArguments(m_args);
1285
oliver@apple.comba848d12014-02-12 17:14:23 +00001286 RefPtr<RegisterID> function;
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001287 RefPtr<RegisterID> base = generator.emitNode(m_base);
1288 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
1289 auto makeFunction = [&] {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001290 if (m_base->isSuperNode()) {
1291 RefPtr<RegisterID> thisValue = generator.ensureThis();
1292 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().applyPublicName());
1293 } else
1294 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001295 };
1296
1297 bool emitCallCheck = !generator.isBuiltinFunction();
sbarati@apple.com07f9fa92017-04-18 19:02:01 +00001298 if (m_distanceToInnermostCallOrApply > maxDistanceToInnermostCallOrApply && emitCallCheck) {
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001299 makeFunction();
1300 CallArguments callArguments(generator, m_args);
1301 generator.emitMove(callArguments.thisRegister(), base.get());
1302 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1303 generator.moveToDestinationIfNeeded(dst, returnValue.get());
1304 return returnValue.get();
1305 }
1306
1307 Ref<Label> realCall = generator.newLabel();
1308 Ref<Label> end = generator.newLabel();
1309 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1310 if (emitCallCheck) {
1311 makeFunction();
oliver@apple.comba848d12014-02-12 17:14:23 +00001312 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
1313 }
1314 if (mayBeCall) {
1315 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
1316 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001317 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
1318 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001319 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
1320 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
1321 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1322 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1323
1324 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
1325 {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001326 Ref<Label> haveThis = generator.newLabel();
1327 Ref<Label> end = generator.newLabel();
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001328 RefPtr<RegisterID> compareResult = generator.newTemporary();
1329 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1330 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
1331 generator.emitMove(thisRegister.get(), value);
1332 generator.emitLoad(index.get(), jsNumber(1));
1333 generator.emitJump(end.get());
1334 generator.emitLabel(haveThis.get());
1335 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1336 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
1337 generator.emitMove(argumentsRegister.get(), value);
1338 generator.emitLoad(index.get(), jsNumber(2));
1339 generator.emitLabel(end.get());
1340 };
1341 generator.emitEnumeration(this, spread->expression(), extractor);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001342 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001343 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +00001344 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
1345 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +00001346 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.parserArena(), 0, 0);
oliver@apple.comfca9a922014-01-31 21:34:38 +00001347 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1348 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +00001349 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001350 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001351 } else {
1352 m_args->m_listNode = m_args->m_listNode->m_next;
1353 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1354 CallArguments callArguments(generator, m_args);
1355 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001356 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001357 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001358 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001359 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +00001360 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001361 CallArguments callArguments(generator, m_args);
1362 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001363 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001364 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001365 } else {
1366 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
oliver@apple.comba848d12014-02-12 17:14:23 +00001367 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1368 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
1369 RefPtr<RegisterID> argsRegister;
1370 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001371 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +00001372
1373 // Function.prototype.apply ignores extra arguments, but we still
1374 // need to evaluate them for side effects.
1375 while ((args = args->m_next))
1376 generator.emitNode(args->m_expr);
1377
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001378 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comd04e0a02014-02-01 01:37:59 +00001379 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001380 if (emitCallCheck) {
1381 generator.emitJump(end.get());
1382 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001383 CallArguments callArguments(generator, m_args);
1384 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001385 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001386 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001387 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001388 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001389 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001390}
1391
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001392// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001393
ggaren@apple.comf3036112013-04-27 23:14:04 +00001394static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001395{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001396 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001397}
1398
1399static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1400{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001401 if (dst == srcDst)
1402 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1403 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1404 emitIncOrDec(generator, srcDst, oper);
1405 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001406}
1407
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001408RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001409{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001410 if (dst == generator.ignoredResult())
1411 return PrefixNode::emitResolve(generator, dst);
1412
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001413 ASSERT(m_expr->isResolveNode());
1414 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1415 const Identifier& ident = resolve->identifier();
1416
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001417 Variable var = generator.variable(ident);
1418 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001419 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001420 RefPtr<RegisterID> localReg = local;
1421 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001422 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001423 localReg = generator.emitMove(generator.tempDestination(dst), local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001424 }
fpizlo@apple.com67202962017-05-10 17:00:22 +00001425 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001426 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1427 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1428 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001429 }
oliver@apple.com75f804e2013-03-07 00:25:20 +00001430
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001431 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001432 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1433 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001434 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001435 if (var.isReadOnly()) {
1436 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1437 if (threwException)
1438 return value.get();
1439 }
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001440 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001441 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001442 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001443 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1444 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001445
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001446 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001447}
1448
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001449RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001450{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001451 if (dst == generator.ignoredResult())
1452 return PrefixNode::emitBracket(generator, dst);
1453
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001454 ASSERT(m_expr->isBracketAccessorNode());
1455 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1456 ExpressionNode* baseNode = bracketAccessor->base();
1457 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001458
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001459 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00001460 RefPtr<RegisterID> property = generator.emitNodeForProperty(subscript);
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001461
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001462 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001463 RefPtr<RegisterID> value;
1464 RefPtr<RegisterID> thisValue;
1465 if (baseNode->isSuperNode()) {
1466 thisValue = generator.ensureThis();
1467 value = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
1468 } else
1469 value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001470 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001471 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001472 if (baseNode->isSuperNode())
1473 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value.get());
1474 else
1475 generator.emitPutByVal(base.get(), property.get(), value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001476 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001477 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001478}
1479
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001480RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001481{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001482 if (dst == generator.ignoredResult())
1483 return PrefixNode::emitDot(generator, dst);
1484
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001485 ASSERT(m_expr->isDotAccessorNode());
1486 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1487 ExpressionNode* baseNode = dotAccessor->base();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001488 bool baseIsSuper = baseNode->isSuperNode();
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001489 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001490
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001491 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1492
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001493 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001494 RefPtr<RegisterID> value;
1495 RefPtr<RegisterID> thisValue;
1496 if (baseIsSuper) {
1497 thisValue = generator.ensureThis();
1498 value = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), ident);
1499 } else
1500 value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001501 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001502 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001503 if (baseIsSuper)
1504 generator.emitPutById(base.get(), thisValue.get(), ident, value.get());
1505 else
1506 generator.emitPutById(base.get(), ident, value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001507 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001508 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001509}
1510
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001511RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001512{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001513 if (m_expr->isResolveNode())
1514 return emitResolve(generator, dst);
1515
1516 if (m_expr->isBracketAccessorNode())
1517 return emitBracket(generator, dst);
1518
1519 if (m_expr->isDotAccessorNode())
1520 return emitDot(generator, dst);
1521
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001522 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001523 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1524 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001525}
1526
1527// ------------------------------ DeleteResolveNode -----------------------------------
1528
1529RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1530{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001531 Variable var = generator.variable(m_ident);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001532 if (var.local()) {
1533 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001534 return generator.emitLoad(generator.finalDestination(dst), false);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001535 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001536
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001537 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001538 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001539 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
oliver@apple.com58c86752013-07-25 04:02:40 +00001540 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001541}
1542
1543// ------------------------------ DeleteBracketNode -----------------------------------
1544
1545RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1546{
1547 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001548 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001549
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001550 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001551 if (m_base->isSuperNode())
1552 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001553 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001554}
1555
1556// ------------------------------ DeleteDotNode -----------------------------------
1557
1558RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1559{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001560 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001561
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001562 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001563 if (m_base->isSuperNode())
1564 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001565 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001566}
1567
1568// ------------------------------ DeleteValueNode -----------------------------------
1569
1570RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1571{
1572 generator.emitNode(generator.ignoredResult(), m_expr);
1573
1574 // delete on a non-location expression ignores the value and returns true
1575 return generator.emitLoad(generator.finalDestination(dst), true);
1576}
1577
1578// ------------------------------ VoidNode -------------------------------------
1579
1580RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1581{
1582 if (dst == generator.ignoredResult()) {
1583 generator.emitNode(generator.ignoredResult(), m_expr);
1584 return 0;
1585 }
1586 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1587 return generator.emitLoad(dst, jsUndefined());
1588}
1589
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001590// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001591
1592RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1593{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001594 Variable var = generator.variable(m_ident);
1595 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001596 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001597 if (dst == generator.ignoredResult())
1598 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001599 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001600 }
1601
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001602 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1603 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001604 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001605 if (dst == generator.ignoredResult())
1606 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001607 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001608}
1609
1610// ------------------------------ TypeOfValueNode -----------------------------------
1611
1612RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1613{
1614 if (dst == generator.ignoredResult()) {
1615 generator.emitNode(generator.ignoredResult(), m_expr);
1616 return 0;
1617 }
1618 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1619 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1620}
1621
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001622// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001623
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001624RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001625{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001626 ASSERT(m_expr->isResolveNode());
1627 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1628 const Identifier& ident = resolve->identifier();
1629
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001630 Variable var = generator.variable(ident);
1631 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001632 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001633 RefPtr<RegisterID> localReg = local;
1634 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001635 generator.emitReadOnlyExceptionIfNeeded(var);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001636 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001637 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com67202962017-05-10 17:00:22 +00001638 generator.invalidateForInContextForLocal(local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001639 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001640 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001641 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001642 generator.emitMove(localReg.get(), tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001643 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001644 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1645 }
fpizlo@apple.com67202962017-05-10 17:00:22 +00001646 generator.invalidateForInContextForLocal(local);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001647 emitIncOrDec(generator, localReg.get(), m_operator);
1648 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001649 }
1650
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001651 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001652 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1653 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001654 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001655 if (var.isReadOnly()) {
1656 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1657 if (threwException)
1658 return value.get();
1659 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001660
oliver@apple.com58c86752013-07-25 04:02:40 +00001661 emitIncOrDec(generator, value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001662 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001663 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001664 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1665 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001666 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001667}
1668
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001669RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001670{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001671 ASSERT(m_expr->isBracketAccessorNode());
1672 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1673 ExpressionNode* baseNode = bracketAccessor->base();
1674 ExpressionNode* subscript = bracketAccessor->subscript();
1675
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001676 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00001677 RefPtr<RegisterID> property = generator.emitNodeForProperty(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001678 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1679
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001680 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001681 RegisterID* value;
1682 RefPtr<RegisterID> thisValue;
1683 if (baseNode->isSuperNode()) {
1684 thisValue = generator.ensureThis();
1685 value = generator.emitGetByVal(propDst.get(), base.get(), thisValue.get(), property.get());
1686 } else
1687 value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001688 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001689 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001690 if (baseNode->isSuperNode())
1691 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
1692 else
1693 generator.emitPutByVal(base.get(), property.get(), value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001694 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001695 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1696}
1697
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001698RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001699{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001700 ASSERT(m_expr->isDotAccessorNode());
1701 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1702 ExpressionNode* baseNode = dotAccessor->base();
1703 const Identifier& ident = dotAccessor->identifier();
1704
1705 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001706 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1707
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001708 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001709 RegisterID* value;
1710 RefPtr<RegisterID> thisValue;
1711 if (baseNode->isSuperNode()) {
1712 thisValue = generator.ensureThis();
1713 value = generator.emitGetById(propDst.get(), base.get(), thisValue.get(), ident);
1714 } else
1715 value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001716 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001717 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001718 if (baseNode->isSuperNode())
1719 generator.emitPutById(base.get(), thisValue.get(), ident, value);
1720 else
1721 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001722 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001723 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1724}
1725
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001726RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001727{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001728 if (m_expr->isResolveNode())
1729 return emitResolve(generator, dst);
1730
1731 if (m_expr->isBracketAccessorNode())
1732 return emitBracket(generator, dst);
1733
1734 if (m_expr->isDotAccessorNode())
1735 return emitDot(generator, dst);
1736
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001737 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001738 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1739 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001740}
1741
1742// ------------------------------ Unary Operation Nodes -----------------------------------
1743
1744RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1745{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001746 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001747 generator.emitExpressionInfo(position(), position(), position());
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00001748 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001749}
1750
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001751// ------------------------------ UnaryPlusNode -----------------------------------
1752
1753RegisterID* UnaryPlusNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1754{
1755 ASSERT(opcodeID() == op_to_number);
1756 RefPtr<RegisterID> src = generator.emitNode(expr());
1757 generator.emitExpressionInfo(position(), position(), position());
1758 return generator.emitToNumber(generator.finalDestination(dst), src.get());
1759}
1760
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001761// ------------------------------ BitwiseNotNode -----------------------------------
1762
1763RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1764{
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00001765 RefPtr<RegisterID> src2 = generator.emitLoad(nullptr, jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001766 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1767 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001768}
1769
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001770// ------------------------------ LogicalNotNode -----------------------------------
1771
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001772void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001773{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00001774 if (UNLIKELY(needsDebugHook()))
1775 generator.emitDebugHook(this);
1776
1777 // Reverse the true and false targets.
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001778 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001779}
1780
1781
1782// ------------------------------ Binary Operation Nodes -----------------------------------
1783
1784// BinaryOpNode::emitStrcat:
1785//
1786// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1787// more values, where we can determine a set of separate op_add operations would be operating on
1788// string values.
1789//
1790// This function expects to be operating on a graph of AST nodes looking something like this:
1791//
1792// (a)... (b)
1793// \ /
1794// (+) (c)
1795// \ /
1796// [d] ((+))
1797// \ /
1798// [+=]
1799//
1800// The assignment operation is optional, if it exists the register holding the value on the
1801// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1802//
1803// The method should be called on the node at the root of the tree of regular binary add
1804// operations (marked in the diagram with a double set of parentheses). This node must
1805// be performing a string concatenation (determined by statically detecting that at least
1806// one child must be a string).
1807//
1808// Since the minimum number of values being concatenated together is expected to be 3, if
1809// a lhs to a concatenating assignment is not provided then the root add should have at
1810// least one left child that is also an add that can be determined to be operating on strings.
1811//
1812RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1813{
1814 ASSERT(isAdd());
1815 ASSERT(resultDescriptor().definitelyIsString());
1816
1817 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1818 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1819 // added first, and the leftmost child is never added, so the vector produced for the
1820 // example above will be [ c, b ].
1821 Vector<ExpressionNode*, 16> reverseExpressionList;
1822 reverseExpressionList.append(m_expr2);
1823
1824 // Examine the left child of the add. So long as this is a string add, add its right-child
1825 // to the list, and keep processing along the left fork.
1826 ExpressionNode* leftMostAddChild = m_expr1;
1827 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1828 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1829 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1830 }
1831
1832 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1833
1834 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1835 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1836 // op_strcat node handle its conversion if required).
1837 if (lhs)
1838 temporaryRegisters.append(generator.newTemporary());
1839
1840 // Emit code for the leftmost node ((a) in the example).
1841 temporaryRegisters.append(generator.newTemporary());
1842 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1843 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1844
1845 // Note on ordering of conversions:
1846 //
1847 // We maintain the same ordering of conversions as we would see if the concatenations
1848 // was performed as a sequence of adds (otherwise this optimization could change
1849 // behaviour should an object have been provided a valueOf or toString method).
1850 //
1851 // Considering the above example, the sequnce of execution is:
1852 // * evaluate operand (a)
1853 // * evaluate operand (b)
1854 // * convert (a) to primitive <- (this would be triggered by the first add)
1855 // * convert (b) to primitive <- (ditto)
1856 // * evaluate operand (c)
1857 // * convert (c) to primitive <- (this would be triggered by the second add)
1858 // And optionally, if there is an assignment:
1859 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1860 //
1861 // As such we do not plant an op to convert the leftmost child now. Instead, use
1862 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1863 // once the second node has been generated. However, if the leftmost child is an
1864 // immediate we can trivially determine that no conversion will be required.
1865 // If this is the case
1866 if (leftMostAddChild->isString())
1867 leftMostAddChildTempRegister = 0;
1868
1869 while (reverseExpressionList.size()) {
1870 ExpressionNode* node = reverseExpressionList.last();
1871 reverseExpressionList.removeLast();
1872
1873 // Emit the code for the current node.
1874 temporaryRegisters.append(generator.newTemporary());
1875 generator.emitNode(temporaryRegisters.last().get(), node);
1876
1877 // On the first iteration of this loop, when we first reach this point we have just
1878 // generated the second node, which means it is time to convert the leftmost operand.
1879 if (leftMostAddChildTempRegister) {
1880 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1881 leftMostAddChildTempRegister = 0; // Only do this once.
1882 }
1883 // Plant a conversion for this node, if necessary.
1884 if (!node->isString())
1885 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1886 }
1887 ASSERT(temporaryRegisters.size() >= 3);
1888
1889 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1890 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1891 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001892 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001893 // If there is an assignment convert the lhs now. This will also copy lhs to
1894 // the temporary register we allocated for it.
1895 if (lhs)
1896 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1897
1898 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1899}
1900
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001901void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001902{
1903 TriState branchCondition;
1904 ExpressionNode* branchExpression;
1905 tryFoldToBranch(generator, branchCondition, branchExpression);
1906
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00001907 if (UNLIKELY(needsDebugHook())) {
1908 if (branchCondition != MixedTriState)
1909 generator.emitDebugHook(this);
1910 }
1911
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001912 if (branchCondition == MixedTriState)
1913 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1914 else if (branchCondition == TrueTriState)
1915 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1916 else
1917 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1918}
1919
1920static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1921{
1922 ResultType expressionType = branchExpression->resultDescriptor();
1923
1924 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1925 return true;
1926 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1927 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1928 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1929 return true;
1930
1931 return false;
1932}
1933
1934void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1935{
1936 branchCondition = MixedTriState;
1937 branchExpression = 0;
1938
1939 ConstantNode* constant = 0;
1940 if (m_expr1->isConstant()) {
1941 constant = static_cast<ConstantNode*>(m_expr1);
1942 branchExpression = m_expr2;
1943 } else if (m_expr2->isConstant()) {
1944 constant = static_cast<ConstantNode*>(m_expr2);
1945 branchExpression = m_expr1;
1946 }
1947
1948 if (!constant)
1949 return;
1950 ASSERT(branchExpression);
1951
1952 OpcodeID opcodeID = this->opcodeID();
1953 JSValue value = constant->jsValue(generator);
1954 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1955 if (!canFoldToBranch)
1956 return;
1957
1958 if (opcodeID == op_eq || opcodeID == op_stricteq)
1959 branchCondition = triState(value.pureToBoolean());
1960 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1961 branchCondition = triState(!value.pureToBoolean());
1962}
1963
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001964RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1965{
1966 OpcodeID opcodeID = this->opcodeID();
1967
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001968 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001969 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001970 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001971 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001972
1973 if (opcodeID == op_neq) {
1974 if (m_expr1->isNull() || m_expr2->isNull()) {
1975 RefPtr<RegisterID> src = generator.tempDestination(dst);
1976 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1977 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1978 }
1979 }
1980
oliver@apple.comece74042012-12-01 00:50:39 +00001981 ExpressionNode* left = m_expr1;
1982 ExpressionNode* right = m_expr2;
1983 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1984 if (left->isString())
1985 std::swap(left, right);
1986 }
1987
1988 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001989 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001990 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001991 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001992 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001993 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1994 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001995 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001996 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001997 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001998 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001999 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00002000 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
2001 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002002 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00002003 if (opcodeID == op_urshift && dst != generator.ignoredResult())
2004 return generator.emitUnaryOp(op_unsigned, result, result);
2005 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002006}
2007
2008RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2009{
2010 if (m_expr1->isNull() || m_expr2->isNull()) {
2011 RefPtr<RegisterID> src = generator.tempDestination(dst);
2012 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
2013 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
2014 }
2015
oliver@apple.comece74042012-12-01 00:50:39 +00002016 ExpressionNode* left = m_expr1;
2017 ExpressionNode* right = m_expr2;
2018 if (left->isString())
2019 std::swap(left, right);
2020
2021 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002022 RefPtr<RegisterID> src2 = generator.emitNode(right);
2023 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002024}
2025
2026RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2027{
oliver@apple.comece74042012-12-01 00:50:39 +00002028 ExpressionNode* left = m_expr1;
2029 ExpressionNode* right = m_expr2;
2030 if (left->isString())
2031 std::swap(left, right);
2032
2033 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002034 RefPtr<RegisterID> src2 = generator.emitNode(right);
2035 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002036}
2037
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002038RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2039{
2040 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002041 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002042 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002043 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002044}
2045
2046RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2047{
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002048 RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
2049 RefPtr<RegisterID> isObject = generator.newTemporary();
2050 RefPtr<RegisterID> isCustom = generator.newTemporary();
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00002051 RefPtr<RegisterID> prototype = generator.newTemporary();
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002052 RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2053 RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
2054 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002055 Ref<Label> custom = generator.newLabel();
2056 Ref<Label> done = generator.newLabel();
2057 Ref<Label> typeError = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002058
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002059 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002060 generator.emitIsObject(isObject.get(), constructor.get());
2061 generator.emitJumpIfFalse(isObject.get(), typeError.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00002062
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002063 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002064 generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002065
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002066 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002067 generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
2068
2069 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2070 generator.emitJumpIfTrue(isCustom.get(), custom.get());
2071
2072 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2073 generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
2074
2075 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2076 generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
2077
2078 generator.emitJump(done.get());
2079
2080 generator.emitLabel(typeError.get());
2081 generator.emitThrowTypeError("Right hand side of instanceof is not an object");
2082
2083 generator.emitLabel(custom.get());
2084
2085 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2086 generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
2087
2088 generator.emitLabel(done.get());
2089
2090 return dstReg.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002091}
2092
keith_miller@apple.com6fc2fb72017-02-09 00:02:20 +00002093// ------------------------------ InNode ----------------------------
2094
2095RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2096{
2097 RefPtr<RegisterID> key = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2098 RefPtr<RegisterID> base = generator.emitNode(m_expr2);
2099 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2100 return generator.emitIn(generator.finalDestination(dst, key.get()), key.get(), base.get());
2101}
2102
2103
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002104// ------------------------------ LogicalOpNode ----------------------------
2105
2106RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2107{
2108 RefPtr<RegisterID> temp = generator.tempDestination(dst);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002109 Ref<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002110
2111 generator.emitNode(temp.get(), m_expr1);
2112 if (m_operator == OpLogicalAnd)
2113 generator.emitJumpIfFalse(temp.get(), target.get());
2114 else
2115 generator.emitJumpIfTrue(temp.get(), target.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002116 generator.emitNodeInTailPosition(temp.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002117 generator.emitLabel(target.get());
2118
2119 return generator.moveToDestinationIfNeeded(dst, temp.get());
2120}
2121
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002122void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002123{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002124 if (UNLIKELY(needsDebugHook()))
2125 generator.emitDebugHook(this);
2126
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002127 Ref<Label> afterExpr1 = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002128 if (m_operator == OpLogicalAnd)
2129 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
2130 else
2131 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
2132 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002133
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002134 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002135}
2136
2137// ------------------------------ ConditionalNode ------------------------------
2138
2139RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2140{
2141 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002142 Ref<Label> beforeElse = generator.newLabel();
2143 Ref<Label> afterElse = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002144
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002145 Ref<Label> beforeThen = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002146 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
2147 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002148
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002149 generator.emitProfileControlFlow(m_expr1->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002150 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002151 generator.emitJump(afterElse.get());
2152
2153 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002154 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002155 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002156
2157 generator.emitLabel(afterElse.get());
2158
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002159 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002160
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002161 return newDst.get();
2162}
2163
2164// ------------------------------ ReadModifyResolveNode -----------------------------------
2165
2166// FIXME: should this be moved to be a method on BytecodeGenerator?
2167static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
2168{
2169 OpcodeID opcodeID;
2170 switch (oper) {
2171 case OpMultEq:
2172 opcodeID = op_mul;
2173 break;
2174 case OpDivEq:
2175 opcodeID = op_div;
2176 break;
2177 case OpPlusEq:
2178 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
2179 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
2180 opcodeID = op_add;
2181 break;
2182 case OpMinusEq:
2183 opcodeID = op_sub;
2184 break;
2185 case OpLShift:
2186 opcodeID = op_lshift;
2187 break;
2188 case OpRShift:
2189 opcodeID = op_rshift;
2190 break;
2191 case OpURShift:
2192 opcodeID = op_urshift;
2193 break;
2194 case OpAndEq:
2195 opcodeID = op_bitand;
2196 break;
2197 case OpXOrEq:
2198 opcodeID = op_bitxor;
2199 break;
2200 case OpOrEq:
2201 opcodeID = op_bitor;
2202 break;
2203 case OpModEq:
2204 opcodeID = op_mod;
2205 break;
utatane.tea@gmail.come9906382016-07-21 07:33:28 +00002206 case OpPowEq:
2207 opcodeID = op_pow;
2208 break;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002209 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00002210 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002211 return dst;
2212 }
2213
2214 RegisterID* src2 = generator.emitNode(m_right);
2215
2216 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2217 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2218 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002219 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00002220 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
2221 if (oper == OpURShift)
2222 return generator.emitUnaryOp(op_unsigned, result, result);
2223 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002224}
2225
2226RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2227{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002228 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002229 Variable var = generator.variable(m_ident);
2230 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002231 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002232 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002233 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002234 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2235 generator.emitProfileType(result, divotStart(), divotEnd());
2236 return result;
ggaren@apple.com6e309822012-09-05 21:44:43 +00002237 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002238
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002239 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002240 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002241 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002242 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002243 generator.emitMove(local, result.get());
2244 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002245 generator.emitProfileType(local, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002246 return generator.moveToDestinationIfNeeded(dst, result.get());
2247 }
2248
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002249 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2250 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002251 generator.emitProfileType(result, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002252 return generator.moveToDestinationIfNeeded(dst, result);
2253 }
2254
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002255 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002256 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2257 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002258 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002259 if (var.isReadOnly()) {
2260 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2261 if (threwException)
2262 return value.get();
2263 }
oliver@apple.com58c86752013-07-25 04:02:40 +00002264 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002265 RegisterID* returnResult = result.get();
2266 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002267 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002268 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2269 }
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002270 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002271}
2272
sbarati@apple.come67fd782016-04-19 01:38:30 +00002273static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
2274{
2275 switch (assignmentContext) {
2276 case AssignmentContext::DeclarationStatement:
2277 return InitializationMode::Initialization;
2278 case AssignmentContext::ConstDeclarationStatement:
2279 return InitializationMode::ConstInitialization;
2280 case AssignmentContext::AssignmentExpression:
2281 return InitializationMode::NotInitialization;
2282 }
2283
2284 ASSERT_NOT_REACHED();
2285 return InitializationMode::NotInitialization;
2286}
2287
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002288// ------------------------------ AssignResolveNode -----------------------------------
2289
2290RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2291{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002292 Variable var = generator.variable(m_ident);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002293 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002294 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002295 RegisterID* result = nullptr;
2296 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2297 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002298
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002299 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002300 result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002301 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002302 generator.emitProfileType(result, var, divotStart(), divotEnd());
2303 } else if (var.isSpecial()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002304 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
2305 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002306 generator.emitMove(local, tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002307 generator.emitProfileType(local, var, divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002308 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002309 result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
2310 } else {
2311 RegisterID* right = generator.emitNode(local, m_right);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002312 generator.emitProfileType(right, var, divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002313 generator.invalidateForInContextForLocal(local);
2314 result = generator.moveToDestinationIfNeeded(dst, right);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002315 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002316
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002317 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002318 generator.liftTDZCheckIfPossible(var);
2319 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002320 }
2321
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002322 if (generator.isStrictMode())
2323 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002324 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002325 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2326 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002327 if (dst == generator.ignoredResult())
2328 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00002329 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002330 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002331 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002332 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2333 if (threwException)
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002334 return result;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002335 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002336 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002337 RegisterID* returnResult = result.get();
2338 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002339 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002340 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2341 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002342
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002343 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002344 generator.liftTDZCheckIfPossible(var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002345 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002346}
2347
2348// ------------------------------ AssignDotNode -----------------------------------
2349
2350RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2351{
2352 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2353 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002354 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002355 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002356 RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
2357 if (m_base->isSuperNode()) {
2358 RefPtr<RegisterID> thisValue = generator.ensureThis();
2359 generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
2360 } else
2361 generator.emitPutById(base.get(), m_ident, forwardResult.get());
2362 generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
2363 return generator.moveToDestinationIfNeeded(dst, forwardResult.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002364}
2365
2366// ------------------------------ ReadModifyDotNode -----------------------------------
2367
2368RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2369{
2370 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2371
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002372 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002373 RefPtr<RegisterID> value;
2374 RefPtr<RegisterID> thisValue;
2375 if (m_base->isSuperNode()) {
2376 thisValue = generator.ensureThis();
2377 value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
2378 } else
2379 value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002380 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()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002381
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002382 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002383 RegisterID* ret;
2384 if (m_base->isSuperNode())
2385 ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
2386 else
2387 ret = generator.emitPutById(base.get(), m_ident, updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002388 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002389 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002390}
2391
2392// ------------------------------ AssignErrorNode -----------------------------------
2393
2394RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2395{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002396 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002397}
2398
2399// ------------------------------ AssignBracketNode -----------------------------------
2400
2401RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2402{
2403 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00002404 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002405 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002406 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002407
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002408 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002409 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00002410
sbarati@apple.com23315d62016-05-09 20:17:23 +00002411 if (isNonIndexStringElement(*m_subscript)) {
2412 if (m_base->isSuperNode()) {
2413 RefPtr<RegisterID> thisValue = generator.ensureThis();
2414 generator.emitPutById(base.get(), thisValue.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2415 } else
2416 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2417 } else {
2418 if (m_base->isSuperNode()) {
2419 RefPtr<RegisterID> thisValue = generator.ensureThis();
2420 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), forwardResult);
2421 } else
2422 generator.emitPutByVal(base.get(), property.get(), forwardResult);
2423 }
akling@apple.come09d0422014-11-13 19:18:43 +00002424
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002425 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00002426 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002427}
2428
2429// ------------------------------ ReadModifyBracketNode -----------------------------------
2430
2431RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2432{
2433 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00002434 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002435
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002436 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002437 RefPtr<RegisterID> value;
2438 RefPtr<RegisterID> thisValue;
2439 if (m_base->isSuperNode()) {
2440 thisValue = generator.ensureThis();
2441 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisValue.get(), property.get());
2442 } else
2443 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002444 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()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002445
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002446 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002447 if (m_base->isSuperNode())
2448 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), updatedValue);
2449 else
2450 generator.emitPutByVal(base.get(), property.get(), updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002451 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002452
2453 return updatedValue;
2454}
2455
2456// ------------------------------ CommaNode ------------------------------------
2457
2458RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2459{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002460 CommaNode* node = this;
2461 for (; node && node->next(); node = node->next())
2462 generator.emitNode(generator.ignoredResult(), node->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002463 return generator.emitNodeInTailPosition(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002464}
2465
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002466// ------------------------------ SourceElements -------------------------------
2467
commit-queue@webkit.org678662c2017-06-29 19:34:03 +00002468
2469inline StatementNode* SourceElements::lastStatement() const
2470{
2471 return m_tail;
2472}
2473
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002474inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2475{
commit-queue@webkit.org678662c2017-06-29 19:34:03 +00002476 for (StatementNode* statement = m_head; statement; statement = statement->next())
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002477 generator.emitNodeInTailPosition(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002478}
2479
2480// ------------------------------ BlockNode ------------------------------------
2481
commit-queue@webkit.org678662c2017-06-29 19:34:03 +00002482inline StatementNode* BlockNode::lastStatement() const
2483{
2484 return m_statements ? m_statements->lastStatement() : 0;
2485}
2486
2487StatementNode* BlockNode::singleStatement() const
2488{
2489 return m_statements ? m_statements->singleStatement() : 0;
2490}
2491
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002492void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002493{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002494 if (!m_statements)
2495 return;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002496 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002497 m_statements->emitBytecode(generator, dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002498 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002499}
2500
2501// ------------------------------ EmptyStatementNode ---------------------------
2502
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002503void EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002504{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002505 RELEASE_ASSERT(needsDebugHook());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002506}
2507
2508// ------------------------------ DebuggerStatementNode ---------------------------
2509
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002510void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002511{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002512 generator.emitDebugHook(DidReachBreakpoint, position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002513}
2514
2515// ------------------------------ ExprStatementNode ----------------------------
2516
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002517void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002518{
2519 ASSERT(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002520 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002521}
2522
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002523// ------------------------------ DeclarationStatement ----------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002524
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002525void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002526{
2527 ASSERT(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002528 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002529}
2530
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002531// ------------------------------ EmptyVarExpression ----------------------------
2532
2533RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2534{
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002535 // It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002536 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002537 return nullptr;
2538
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002539 Variable var = generator.variable(m_ident);
2540 if (RegisterID* local = var.local())
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002541 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002542 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002543 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2544 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002545 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002546 }
2547
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002548 return nullptr;
2549}
2550
2551// ------------------------------ EmptyLetExpression ----------------------------
2552
2553RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2554{
2555 // Lexical declarations like 'let' must move undefined into their variables so we don't
2556 // get TDZ errors for situations like this: `let x; x;`
2557 Variable var = generator.variable(m_ident);
2558 if (RegisterID* local = var.local()) {
2559 generator.emitLoad(local, jsUndefined());
sbarati@apple.com180ae512017-07-06 18:43:41 +00002560 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002561 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002562 } else {
2563 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2564 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002565 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002566 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002567 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002568
sbarati@apple.coma5cf2f12016-03-29 22:11:24 +00002569 generator.liftTDZCheckIfPossible(var);
2570
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002571 // It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002572 return nullptr;
2573}
2574
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002575// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002576
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002577static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002578{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002579 if (statementNode->isBlock())
2580 return static_cast<BlockNode*>(statementNode)->singleStatement();
2581 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002582}
2583
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002584bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2585 Label*& trueTarget, FallThroughMode& fallThroughMode)
2586{
2587 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2588 if (!singleStatement)
2589 return false;
2590
2591 if (singleStatement->isBreak()) {
2592 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2593 Label* target = breakNode->trivialTarget(generator);
2594 if (!target)
2595 return false;
2596 trueTarget = target;
2597 fallThroughMode = FallThroughMeansFalse;
2598 return true;
2599 }
2600
2601 if (singleStatement->isContinue()) {
2602 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2603 Label* target = continueNode->trivialTarget(generator);
2604 if (!target)
2605 return false;
2606 trueTarget = target;
2607 fallThroughMode = FallThroughMeansFalse;
2608 return true;
2609 }
2610
2611 return false;
2612}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002613
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002614void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002615{
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002616 Ref<Label> beforeThen = generator.newLabel();
2617 Ref<Label> beforeElse = generator.newLabel();
2618 Ref<Label> afterElse = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002619
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002620 Label* trueTarget = beforeThen.ptr();
2621 Label& falseTarget = beforeElse.get();
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002622 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2623 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2624
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002625 generator.emitNodeInConditionContext(m_condition, *trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002626 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002627 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002628
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002629 if (!didFoldIfBlock) {
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002630 generator.emitNodeInTailPosition(dst, m_ifBlock);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002631 if (m_elseBlock)
2632 generator.emitJump(afterElse.get());
2633 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002634
2635 generator.emitLabel(beforeElse.get());
2636
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002637 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002638 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002639 generator.emitNodeInTailPosition(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002640 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002641
2642 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002643 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2644 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002645}
2646
2647// ------------------------------ DoWhileNode ----------------------------------
2648
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002649void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002650{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002651 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002652
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002653 Ref<Label> topOfLoop = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002654 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002655 generator.emitLoopHint();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002656
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002657 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002658
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002659 generator.emitLabel(*scope->continueTarget());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002660 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002661
2662 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002663}
2664
2665// ------------------------------ WhileNode ------------------------------------
2666
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002667void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002668{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002669 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002670 Ref<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002671
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002672 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002673
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002674 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002675 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002676
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002677 generator.emitProfileControlFlow(m_statement->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002678 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002679
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002680 generator.emitLabel(*scope->continueTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002681
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002682 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002683
2684 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002685
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002686 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002687}
2688
2689// ------------------------------ ForNode --------------------------------------
2690
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002691void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002692{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002693 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002694
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002695 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002696 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002697
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002698 if (m_expr1)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002699 generator.emitNode(generator.ignoredResult(), m_expr1);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002700
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002701 Ref<Label> topOfLoop = generator.newLabel();
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002702 if (m_expr2)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002703 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002704
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002705 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002706 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002707 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002708
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002709 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002710
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002711 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002712 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002713 if (m_expr3)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002714 generator.emitNode(generator.ignoredResult(), m_expr3);
2715
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002716 if (m_expr2)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002717 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002718 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002719 generator.emitJump(topOfLoop.get());
2720
2721 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002722 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002723 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002724}
2725
2726// ------------------------------ ForInNode ------------------------------------
2727
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002728RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002729{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002730 if (m_lexpr->isResolveNode()) {
2731 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002732 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002733 }
2734
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002735 if (m_lexpr->isDestructuringNode()) {
2736 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002737 auto binding = assignNode->bindings();
2738 if (!binding->isBindingNode())
2739 return nullptr;
2740
2741 auto simpleBinding = static_cast<BindingNode*>(binding);
2742 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002743 Variable var = generator.variable(ident);
2744 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002745 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002746 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002747 }
2748
2749 return nullptr;
2750}
2751
2752void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2753{
sbarati@apple.com180ae512017-07-06 18:43:41 +00002754 auto lambdaEmitResolveVariable = [&] (const Identifier& ident) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002755 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002756 if (RegisterID* local = var.local()) {
2757 if (var.isReadOnly())
2758 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002759 generator.emitMove(local, propertyName);
sbarati@apple.com180ae512017-07-06 18:43:41 +00002760 generator.invalidateForInContextForLocal(local);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002761 } else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002762 if (generator.isStrictMode())
2763 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002764 if (var.isReadOnly())
2765 generator.emitReadOnlyExceptionIfNeeded(var);
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00002766 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002767 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00002768 generator.emitPutToScope(scope.get(), var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002769 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002770 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002771 };
2772
2773 if (m_lexpr->isResolveNode()) {
2774 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2775 lambdaEmitResolveVariable(ident);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002776 return;
2777 }
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002778
2779 if (m_lexpr->isAssignResolveNode()) {
2780 const Identifier& ident = static_cast<AssignResolveNode*>(m_lexpr)->identifier();
2781 lambdaEmitResolveVariable(ident);
2782 return;
2783 }
2784
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002785 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002786 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2787 const Identifier& ident = assignNode->identifier();
sbarati@apple.com23315d62016-05-09 20:17:23 +00002788 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002789 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002790 if (assignNode->base()->isSuperNode()) {
2791 RefPtr<RegisterID> thisValue = generator.ensureThis();
2792 generator.emitPutById(base.get(), thisValue.get(), ident, propertyName);
2793 } else
2794 generator.emitPutById(base.get(), ident, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002795 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002796 return;
2797 }
2798 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002799 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002800 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00002801 RefPtr<RegisterID> subscript = generator.emitNodeForProperty(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002802 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002803 if (assignNode->base()->isSuperNode()) {
2804 RefPtr<RegisterID> thisValue = generator.ensureThis();
2805 generator.emitPutByVal(base.get(), thisValue.get(), subscript.get(), propertyName);
2806 } else
2807 generator.emitPutByVal(base.get(), subscript.get(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002808 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002809 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002810 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002811
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002812 if (m_lexpr->isDestructuringNode()) {
2813 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002814 auto binding = assignNode->bindings();
2815 if (!binding->isBindingNode()) {
2816 assignNode->bindings()->bindValue(generator, propertyName);
2817 return;
2818 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002819
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002820 auto simpleBinding = static_cast<BindingNode*>(binding);
2821 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002822 Variable var = generator.variable(ident);
2823 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002824 assignNode->bindings()->bindValue(generator, propertyName);
2825 return;
2826 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002827 generator.emitMove(var.local(), propertyName);
sbarati@apple.com180ae512017-07-06 18:43:41 +00002828 generator.invalidateForInContextForLocal(var.local());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002829 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002830 return;
2831 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002832
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002833 RELEASE_ASSERT_NOT_REACHED();
2834}
2835
commit-queue@webkit.org3057eed2016-09-21 22:52:37 +00002836void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002837{
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002838 if (!m_lexpr->isAssignResolveNode() && !m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002839 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002840 return;
2841 }
2842
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002843 Ref<Label> end = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002844
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002845 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002846 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002847
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002848 if (m_lexpr->isAssignResolveNode())
2849 generator.emitNode(generator.ignoredResult(), m_lexpr);
2850
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002851 RefPtr<RegisterID> base = generator.newTemporary();
2852 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002853 RefPtr<RegisterID> enumerator;
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002854
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002855 generator.emitNode(base.get(), m_expr);
2856 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002857 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002858
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002859 // Pause at the assignment expression for each for..in iteration.
2860 generator.emitDebugHook(m_lexpr);
2861
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002862 int profilerStartOffset = m_statement->startOffset();
2863 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002864
2865 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2866
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002867 // Indexed property loop.
2868 {
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002869 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002870 Ref<Label> loopStart = generator.newLabel();
2871 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002872
msaboff@apple.comb644c252015-03-24 10:05:21 +00002873 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002874 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2875 RefPtr<RegisterID> propertyName = generator.newTemporary();
2876
2877 generator.emitLabel(loopStart.get());
2878 generator.emitLoopHint();
2879
2880 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2881 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2882 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002883 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002884
2885 generator.emitToIndexString(propertyName.get(), i.get());
2886 this->emitLoopHeader(generator, propertyName.get());
2887
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002888 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002889
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002890 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002891 generator.emitNode(dst, m_statement);
2892 generator.popIndexedForInScope(local.get());
2893
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002894 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002895
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002896 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002897 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002898 generator.emitInc(i.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002899 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002900 generator.emitJump(loopStart.get());
2901
2902 generator.emitLabel(scope->breakTarget());
2903 generator.emitJump(end.get());
2904 generator.emitLabel(loopEnd.get());
2905 }
2906
2907 // Structure property loop.
2908 {
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002909 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002910 Ref<Label> loopStart = generator.newLabel();
2911 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002912
msaboff@apple.comb644c252015-03-24 10:05:21 +00002913 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002914 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002915 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002916
2917 generator.emitLabel(loopStart.get());
2918 generator.emitLoopHint();
2919
2920 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2921 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002922 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002923 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002924
2925 this->emitLoopHeader(generator, propertyName.get());
2926
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002927 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002928
msaboff@apple.comb644c252015-03-24 10:05:21 +00002929 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002930 generator.emitNode(dst, m_statement);
2931 generator.popStructureForInScope(local.get());
2932
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002933 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002934
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002935 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002936 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002937 generator.emitInc(enumeratorIndex.get());
2938 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002939 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002940 generator.emitJump(loopStart.get());
2941
2942 generator.emitLabel(scope->breakTarget());
2943 generator.emitJump(end.get());
2944 generator.emitLabel(loopEnd.get());
2945 }
2946
2947 // Generic property loop.
2948 {
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002949 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002950 Ref<Label> loopStart = generator.newLabel();
2951 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002952
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002953 RefPtr<RegisterID> propertyName = generator.newTemporary();
2954
msaboff@apple.comb644c252015-03-24 10:05:21 +00002955 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002956
2957 generator.emitLabel(loopStart.get());
2958 generator.emitLoopHint();
2959
msaboff@apple.comb644c252015-03-24 10:05:21 +00002960 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2961 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2962
2963 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002964 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002965
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002966 this->emitLoopHeader(generator, propertyName.get());
2967
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002968 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002969
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002970 generator.emitNode(dst, m_statement);
2971
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002972 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002973 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002974 generator.emitInc(enumeratorIndex.get());
2975 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002976 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
msaboff@apple.comb644c252015-03-24 10:05:21 +00002977 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002978
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002979 generator.emitLabel(scope->breakTarget());
2980 generator.emitJump(end.get());
2981 generator.emitLabel(loopEnd.get());
2982 }
2983
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002984 generator.emitLabel(end.get());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002985 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002986 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002987}
2988
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002989// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002990void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2991{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002992 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002993 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002994 return;
2995 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002996
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002997 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002998 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002999 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00003000 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00003001 if (m_lexpr->isResolveNode()) {
3002 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003003 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00003004 if (RegisterID* local = var.local()) {
3005 if (var.isReadOnly())
3006 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003007 generator.emitMove(local, value);
sbarati@apple.com180ae512017-07-06 18:43:41 +00003008 generator.invalidateForInContextForLocal(local);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00003009 } else {
oliver@apple.com72f8a822013-10-17 01:02:34 +00003010 if (generator.isStrictMode())
3011 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00003012 if (var.isReadOnly())
3013 generator.emitReadOnlyExceptionIfNeeded(var);
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00003014 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00003015 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00003016 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
oliver@apple.com72f8a822013-10-17 01:02:34 +00003017 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003018 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00003019 } else if (m_lexpr->isDotAccessorNode()) {
3020 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
3021 const Identifier& ident = assignNode->identifier();
3022 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3023
3024 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003025 if (assignNode->base()->isSuperNode()) {
3026 RefPtr<RegisterID> thisValue = generator.ensureThis();
3027 generator.emitPutById(base.get(), thisValue.get(), ident, value);
3028 } else
3029 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003030 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00003031 } else if (m_lexpr->isBracketAccessorNode()) {
3032 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
3033 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00003034 RegisterID* subscript = generator.emitNodeForProperty(assignNode->subscript());
oliver@apple.com72f8a822013-10-17 01:02:34 +00003035
3036 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003037 if (assignNode->base()->isSuperNode()) {
3038 RefPtr<RegisterID> thisValue = generator.ensureThis();
3039 generator.emitPutByVal(base.get(), thisValue.get(), subscript, value);
3040 } else
3041 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003042 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00003043 } else {
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003044 ASSERT(m_lexpr->isDestructuringNode());
3045 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00003046 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00003047 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003048 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00003049 generator.emitNode(dst, m_statement);
3050 };
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003051 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
3052 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003053 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00003054}
3055
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003056// ------------------------------ ContinueNode ---------------------------------
3057
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003058Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
3059{
3060 if (generator.shouldEmitDebugHooks())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003061 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003062
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003063 RefPtr<LabelScope> scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003064 ASSERT(scope);
3065
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00003066 if (generator.labelScopeDepth() != scope->scopeDepth())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003067 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003068
3069 return scope->continueTarget();
3070}
3071
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003072void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003073{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003074 RefPtr<LabelScope> scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003075 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003076
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003077 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), *scope->continueTarget());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003078 if (!hasFinally) {
3079 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3080 generator.restoreScopeRegister(lexicalScopeIndex);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003081 generator.emitJump(*scope->continueTarget());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003082 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003083
3084 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003085}
3086
3087// ------------------------------ BreakNode ------------------------------------
3088
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003089Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
3090{
3091 if (generator.shouldEmitDebugHooks())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003092 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003093
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003094 RefPtr<LabelScope> scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003095 ASSERT(scope);
3096
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00003097 if (generator.labelScopeDepth() != scope->scopeDepth())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003098 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003099
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003100 return &scope->breakTarget();
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003101}
3102
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003103void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003104{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003105 RefPtr<LabelScope> scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003106 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003107
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003108 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget());
3109 if (!hasFinally) {
3110 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3111 generator.restoreScopeRegister(lexicalScopeIndex);
3112 generator.emitJump(scope->breakTarget());
3113 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003114
3115 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003116}
3117
3118// ------------------------------ ReturnNode -----------------------------------
3119
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003120void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003121{
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003122 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003123
3124 if (dst == generator.ignoredResult())
3125 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00003126
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003127 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003128
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003129 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003130
3131 bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());
3132 if (!hasFinally) {
3133 generator.emitWillLeaveCallFrameDebugHook();
3134 generator.emitReturn(returnRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003135 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00003136
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003137 generator.emitProfileControlFlow(endOffset());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003138 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
3139 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
3140 if (generator.vm()->controlFlowProfiler())
3141 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003142}
3143
3144// ------------------------------ WithNode -------------------------------------
3145
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003146void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003147{
ggaren@apple.com170d6f22012-09-02 21:27:23 +00003148 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003149 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003150 generator.emitPushWithScope(scope.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003151 generator.emitNodeInTailPosition(dst, m_statement);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003152 generator.emitPopWithScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003153}
3154
3155// ------------------------------ CaseClauseNode --------------------------------
3156
3157inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3158{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003159 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003160 if (!m_statements)
3161 return;
3162 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003163}
3164
3165// ------------------------------ CaseBlockNode --------------------------------
3166
3167enum SwitchKind {
3168 SwitchUnset = 0,
3169 SwitchNumber = 1,
3170 SwitchString = 2,
3171 SwitchNeither = 3
3172};
3173
3174static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
3175{
3176 for (; list; list = list->getNext()) {
3177 ExpressionNode* clauseExpression = list->getClause()->expr();
3178 literalVector.append(clauseExpression);
3179 if (clauseExpression->isNumber()) {
3180 double value = static_cast<NumberNode*>(clauseExpression)->value();
3181 int32_t intVal = static_cast<int32_t>(value);
3182 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
3183 typeForTable = SwitchNeither;
3184 break;
3185 }
3186 if (intVal < min_num)
3187 min_num = intVal;
3188 if (intVal > max_num)
3189 max_num = intVal;
3190 typeForTable = SwitchNumber;
3191 continue;
3192 }
3193 if (clauseExpression->isString()) {
3194 if (typeForTable & ~SwitchString) {
3195 typeForTable = SwitchNeither;
3196 break;
3197 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00003198 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00003199 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00003200 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003201 if (intVal < min_num)
3202 min_num = intVal;
3203 if (intVal > max_num)
3204 max_num = intVal;
3205 }
3206 typeForTable = SwitchString;
3207 continue;
3208 }
3209 typeForTable = SwitchNeither;
3210 break;
3211 }
3212}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003213
3214static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003215{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003216 size_t length = 0;
3217 for (ClauseListNode* node = list1; node; node = node->getNext())
3218 ++length;
3219 for (ClauseListNode* node = list2; node; node = node->getNext())
3220 ++length;
3221 return length;
3222}
3223
3224SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
3225{
3226 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
3227 return SwitchInfo::SwitchNone;
3228
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003229 SwitchKind typeForTable = SwitchUnset;
3230 bool singleCharacterSwitch = true;
3231
3232 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3233 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3234
3235 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
3236 return SwitchInfo::SwitchNone;
3237
3238 if (typeForTable == SwitchNumber) {
3239 int32_t range = max_num - min_num;
3240 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3241 return SwitchInfo::SwitchImmediate;
3242 return SwitchInfo::SwitchNone;
3243 }
3244
3245 ASSERT(typeForTable == SwitchString);
3246
3247 if (singleCharacterSwitch) {
3248 int32_t range = max_num - min_num;
3249 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3250 return SwitchInfo::SwitchCharacter;
3251 }
3252
3253 return SwitchInfo::SwitchString;
3254}
3255
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003256void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003257{
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003258 Vector<Ref<Label>, 8> labelVector;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003259 Vector<ExpressionNode*, 8> literalVector;
3260 int32_t min_num = std::numeric_limits<int32_t>::max();
3261 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003262 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003263
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003264 Ref<Label> defaultLabel = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003265 if (switchType != SwitchInfo::SwitchNone) {
3266 // Prepare the various labels
3267 for (uint32_t i = 0; i < literalVector.size(); i++)
3268 labelVector.append(generator.newLabel());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003269 generator.beginSwitch(switchExpression, switchType);
3270 } else {
3271 // Setup jumps
3272 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3273 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3274 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3275 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3276 labelVector.append(generator.newLabel());
3277 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3278 }
3279
3280 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3281 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3282 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3283 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3284 labelVector.append(generator.newLabel());
3285 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3286 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003287 generator.emitJump(defaultLabel.get());
3288 }
3289
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003290 size_t i = 0;
3291 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3292 generator.emitLabel(labelVector[i++].get());
3293 list->getClause()->emitBytecode(generator, dst);
3294 }
3295
3296 if (m_defaultClause) {
3297 generator.emitLabel(defaultLabel.get());
3298 m_defaultClause->emitBytecode(generator, dst);
3299 }
3300
3301 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3302 generator.emitLabel(labelVector[i++].get());
3303 list->getClause()->emitBytecode(generator, dst);
3304 }
3305 if (!m_defaultClause)
3306 generator.emitLabel(defaultLabel.get());
3307
3308 ASSERT(i == labelVector.size());
3309 if (switchType != SwitchInfo::SwitchNone) {
3310 ASSERT(labelVector.size() == literalVector.size());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003311 generator.endSwitch(labelVector.size(), labelVector, literalVector.data(), defaultLabel.get(), min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003312 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003313}
3314
3315// ------------------------------ SwitchNode -----------------------------------
3316
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003317void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003318{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003319 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003320
3321 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003322
sbarati@apple.combdbba812015-12-19 00:19:41 +00003323 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::DoNotOptimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003324 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003325 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003326
3327 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003328 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003329}
3330
3331// ------------------------------ LabelNode ------------------------------------
3332
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003333void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003334{
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003335 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003336
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003337 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00003338 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003339
3340 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003341}
3342
3343// ------------------------------ ThrowNode ------------------------------------
3344
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003345void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003346{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003347 if (dst == generator.ignoredResult())
3348 dst = 0;
3349 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003350 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003351 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003352
3353 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003354}
3355
3356// ------------------------------ TryNode --------------------------------------
3357
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003358void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003359{
3360 // NOTE: The catch and finally blocks must be labeled explicitly, so the
3361 // optimizer knows they may be jumped to from anywhere.
3362
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003363 ASSERT(m_catchBlock || m_finallyBlock);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003364 BytecodeGenerator::CompletionRecordScope completionRecordScope(generator, m_finallyBlock);
3365
3366 RefPtr<Label> catchLabel;
3367 RefPtr<Label> catchEndLabel;
3368 RefPtr<Label> finallyViaThrowLabel;
3369 RefPtr<Label> finallyLabel;
3370 RefPtr<Label> finallyEndLabel;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003371
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003372 Ref<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003373 generator.emitLabel(tryStartLabel.get());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003374
3375 if (m_finallyBlock) {
3376 finallyViaThrowLabel = generator.newLabel();
3377 finallyLabel = generator.newLabel();
3378 finallyEndLabel = generator.newLabel();
3379
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003380 generator.pushFinallyControlFlowScope(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003381 }
3382 if (m_catchBlock) {
3383 catchLabel = generator.newLabel();
3384 catchEndLabel = generator.newLabel();
3385 }
3386
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003387 Label& tryHandlerLabel = m_catchBlock ? *catchLabel : *finallyViaThrowLabel;
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003388 HandlerType tryHandlerType = m_catchBlock ? HandlerType::Catch : HandlerType::Finally;
3389 TryData* tryData = generator.pushTry(tryStartLabel.get(), tryHandlerLabel, tryHandlerType);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003390
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003391 generator.emitNode(dst, m_tryBlock);
3392
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003393 if (m_finallyBlock)
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003394 generator.emitJump(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003395 else
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003396 generator.emitJump(*catchEndLabel);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003397
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003398 Ref<Label> endTryLabel = generator.newEmittedLabel();
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003399 generator.popTry(tryData, endTryLabel.get());
3400
3401 if (m_catchBlock) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003402 // Uncaught exception path: the catch block.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003403 generator.emitLabel(*catchLabel);
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003404 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003405 RegisterID* unused = generator.newTemporary();
3406 generator.emitCatch(unused, thrownValueRegister.get());
3407 generator.restoreScopeRegister();
3408
3409 TryData* tryData = nullptr;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003410 if (m_finallyBlock) {
3411 // If the catch block throws an exception and we have a finally block, then the finally
3412 // block should "catch" that exception.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003413 tryData = generator.pushTry(*catchLabel, *finallyViaThrowLabel, HandlerType::Finally);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003414 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00003415
utatane.tea@gmail.comc2a96e22017-07-31 16:15:32 +00003416 if (m_catchPattern) {
3417 generator.emitPushCatchScope(m_lexicalVariables);
3418 m_catchPattern->bindValue(generator, thrownValueRegister.get());
3419 }
3420
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003421 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003422 if (m_finallyBlock)
3423 generator.emitNode(dst, m_catchBlock);
3424 else
3425 generator.emitNodeInTailPosition(dst, m_catchBlock);
msaboff@apple.com78461ac2016-06-02 04:07:14 +00003426 generator.emitLoad(thrownValueRegister.get(), jsUndefined());
utatane.tea@gmail.comc2a96e22017-07-31 16:15:32 +00003427
3428 if (m_catchPattern)
3429 generator.emitPopCatchScope(m_lexicalVariables);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003430
3431 if (m_finallyBlock) {
3432 generator.emitSetCompletionType(CompletionType::Normal);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003433 generator.emitJump(*finallyLabel);
3434 generator.popTry(tryData, *finallyViaThrowLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003435 }
3436
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003437 generator.emitLabel(*catchEndLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003438 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003439 }
3440
3441 if (m_finallyBlock) {
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003442 FinallyContext finallyContext = generator.popFinallyControlFlowScope();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003443
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003444 // Entry to the finally block for CompletionType::Throw.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003445 generator.emitLabel(*finallyViaThrowLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003446 RegisterID* unused = generator.newTemporary();
3447 generator.emitCatch(generator.completionValueRegister(), unused);
3448 generator.emitSetCompletionType(CompletionType::Throw);
3449
3450 // Entry to the finally block for CompletionTypes other than Throw.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003451 generator.emitLabel(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003452 generator.restoreScopeRegister();
3453
3454 RefPtr<RegisterID> savedCompletionTypeRegister = generator.newTemporary();
3455 generator.emitMove(savedCompletionTypeRegister.get(), generator.completionTypeRegister());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003456
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003457 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003458 generator.emitProfileControlFlow(finallyStartOffset);
commit-queue@webkit.org678662c2017-06-29 19:34:03 +00003459 generator.emitNodeInTailPosition(dst, m_finallyBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003460
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003461 generator.emitFinallyCompletion(finallyContext, savedCompletionTypeRegister.get(), *finallyEndLabel);
3462 generator.emitLabel(*finallyEndLabel);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003463 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003464 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003465}
3466
3467// ------------------------------ ScopeNode -----------------------------
3468
3469inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
3470{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003471 if (!m_statements)
3472 return;
3473 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003474}
3475
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003476static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
3477{
3478 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
3479
3480 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3481 generator.emitLoad(dstRegister.get(), jsUndefined());
3482 generator.emitProfileControlFlow(scopeNode.startStartOffset());
3483 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
3484
3485 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
3486 generator.emitEnd(dstRegister.get());
3487}
3488
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003489// ------------------------------ ProgramNode -----------------------------
3490
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003491void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003492{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003493 emitProgramNodeBytecode(generator, *this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003494}
3495
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003496// ------------------------------ ModuleProgramNode --------------------
3497
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003498void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003499{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003500 emitProgramNodeBytecode(generator, *this);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003501}
3502
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003503// ------------------------------ EvalNode -----------------------------
3504
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003505void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003506{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003507 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003508
3509 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3510 generator.emitLoad(dstRegister.get(), jsUndefined());
3511 emitStatementsBytecode(generator, dstRegister.get());
3512
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003513 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003514 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003515}
3516
ggaren@apple.come7afe402015-08-10 20:24:35 +00003517// ------------------------------ FunctionNode -----------------------------
ggaren@apple.com6f851d72014-12-04 23:47:49 +00003518
3519void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003520{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00003521 if (generator.vm()->typeProfiler()) {
utatane.tea@gmail.com3e031ac2017-03-16 05:12:53 +00003522 // If the parameter list is non simple one, it is handled in bindValue's code.
3523 if (m_parameters->isSimpleParameterList()) {
3524 for (size_t i = 0; i < m_parameters->size(); i++) {
3525 BindingNode* bindingNode = static_cast<BindingNode*>(m_parameters->at(i).first);
3526 RegisterID reg(CallFrame::argumentOffset(i));
3527 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, bindingNode->divotStart(), bindingNode->divotEnd());
3528 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003529 }
3530 }
3531
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003532 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003533 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003534
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003535 switch (generator.parseMode()) {
commit-queue@webkit.org67795122017-04-25 06:52:04 +00003536 case SourceParseMode::GeneratorWrapperFunctionMode:
3537 case SourceParseMode::GeneratorWrapperMethodMode: {
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003538 StatementNode* singleStatement = this->singleStatement();
3539 ASSERT(singleStatement->isExprStatement());
3540 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3541 ExpressionNode* expr = exprStatement->expr();
3542 ASSERT(expr->isFuncExprNode());
3543 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003544
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003545 RefPtr<RegisterID> next = generator.newTemporary();
3546 generator.emitNode(next.get(), funcExpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003547
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003548 if (generator.superBinding() == SuperBinding::Needed) {
3549 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3550 emitPutHomeObject(generator, next.get(), homeObject.get());
3551 }
3552
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003553 generator.emitPutGeneratorFields(next.get());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003554
mark.lam@apple.comfa35e782013-11-19 21:55:16 +00003555 ASSERT(startOffset() >= lineStartOffset());
3556 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003557 generator.emitReturn(generator.generatorRegister());
3558 break;
3559 }
3560
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003561 case SourceParseMode::AsyncFunctionMode:
3562 case SourceParseMode::AsyncMethodMode:
3563 case SourceParseMode::AsyncArrowFunctionMode: {
3564 StatementNode* singleStatement = this->singleStatement();
3565 ASSERT(singleStatement->isExprStatement());
3566 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3567 ExpressionNode* expr = exprStatement->expr();
3568 ASSERT(expr->isFuncExprNode());
3569 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
3570
3571 RefPtr<RegisterID> next = generator.newTemporary();
3572 generator.emitNode(next.get(), funcExpr);
3573
gskachkov@gmail.comc78531a2017-01-10 21:13:33 +00003574 if (generator.superBinding() == SuperBinding::Needed || (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isSuperUsedInInnerArrowFunction())) {
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003575 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3576 emitPutHomeObject(generator, next.get(), homeObject.get());
3577 }
gskachkov@gmail.com48a2a9a2017-01-19 17:10:31 +00003578
3579 if (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isThisUsedInInnerArrowFunction())
3580 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003581
3582 generator.emitPutGeneratorFields(next.get());
3583
3584 ASSERT(startOffset() >= lineStartOffset());
3585 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3586
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003587 // load and call @asyncFunctionResume
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003588 auto var = generator.variable(generator.propertyNames().builtinNames().asyncFunctionResumePrivateName());
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003589 RefPtr<RegisterID> scope = generator.newTemporary();
3590 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003591 RefPtr<RegisterID> asyncFunctionResume = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003592
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003593 CallArguments args(generator, nullptr, 4);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003594 unsigned argumentCount = 0;
3595 generator.emitLoad(args.thisRegister(), jsUndefined());
3596 generator.emitMove(args.argumentRegister(argumentCount++), generator.generatorRegister());
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003597 generator.emitMove(args.argumentRegister(argumentCount++), generator.promiseCapabilityRegister());
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003598 generator.emitLoad(args.argumentRegister(argumentCount++), jsUndefined());
3599 generator.emitLoad(args.argumentRegister(argumentCount++), jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
3600 // JSTextPosition(int _line, int _offset, int _lineStartOffset)
3601 JSTextPosition divot(firstLine(), startOffset(), lineStartOffset());
3602
3603 RefPtr<RegisterID> result = generator.newTemporary();
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003604 generator.emitCallInTailPosition(result.get(), asyncFunctionResume.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003605 generator.emitReturn(result.get());
3606 break;
3607 }
3608
3609 case SourceParseMode::AsyncArrowFunctionBodyMode:
3610 case SourceParseMode::AsyncFunctionBodyMode:
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003611 case SourceParseMode::GeneratorBodyMode: {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003612 Ref<Label> generatorBodyLabel = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003613 {
3614 RefPtr<RegisterID> condition = generator.newTemporary();
3615 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))));
3616 generator.emitJumpIfTrue(condition.get(), generatorBodyLabel.get());
3617
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003618 Ref<Label> throwLabel = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003619 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))));
3620 generator.emitJumpIfTrue(condition.get(), throwLabel.get());
3621
3622 generator.emitReturn(generator.generatorValueRegister());
3623
3624 generator.emitLabel(throwLabel.get());
3625 generator.emitThrow(generator.generatorValueRegister());
3626 }
3627
3628 generator.emitLabel(generatorBodyLabel.get());
3629
3630 emitStatementsBytecode(generator, generator.ignoredResult());
3631
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003632 Ref<Label> done = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003633 generator.emitLabel(done.get());
3634 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003635 break;
3636 }
3637
3638 default: {
3639 emitStatementsBytecode(generator, generator.ignoredResult());
3640
3641 StatementNode* singleStatement = this->singleStatement();
3642 ReturnNode* returnNode = 0;
3643
3644 // Check for a return statement at the end of a function composed of a single block.
3645 if (singleStatement && singleStatement->isBlock()) {
3646 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
3647 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
3648 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
3649 }
3650
3651 // If there is no return we must automatically insert one.
3652 if (!returnNode) {
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003653 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isSuperCallUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +00003654 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
3655
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003656 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
3657 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
3658 ASSERT(startOffset() >= lineStartOffset());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003659 generator.emitWillLeaveCallFrameDebugHook();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003660 generator.emitReturn(r0);
3661 return;
3662 }
3663 break;
3664 }
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003665 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003666}
3667
3668// ------------------------------ FuncDeclNode ---------------------------------
3669
sbarati@apple.come86176c2016-04-07 21:01:42 +00003670void FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003671{
sbarati@apple.come86176c2016-04-07 21:01:42 +00003672 generator.hoistSloppyModeFunctionIfNecessary(metadata()->ident());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003673}
3674
3675// ------------------------------ FuncExprNode ---------------------------------
3676
3677RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3678{
3679 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3680}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003681
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00003682// ------------------------------ ArrowFuncExprNode ---------------------------------
3683
3684RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3685{
3686 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3687}
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003688
mark.lam@apple.com43137872016-03-17 14:58:57 +00003689// ------------------------------ MethodDefinitionNode ---------------------------------
3690
3691RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3692{
3693 return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
3694}
3695
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003696// ------------------------------ YieldExprNode --------------------------------
3697
3698RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3699{
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003700 if (!delegate()) {
3701 RefPtr<RegisterID> arg = nullptr;
3702 if (argument()) {
3703 arg = generator.newTemporary();
3704 generator.emitNode(arg.get(), argument());
3705 } else
3706 arg = generator.emitLoad(nullptr, jsUndefined());
3707 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3708 if (dst == generator.ignoredResult())
3709 return nullptr;
3710 return generator.emitMove(generator.finalDestination(dst), value.get());
3711 }
3712 RefPtr<RegisterID> arg = generator.newTemporary();
3713 generator.emitNode(arg.get(), argument());
3714 RefPtr<RegisterID> value = generator.emitDelegateYield(arg.get(), this);
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003715 if (dst == generator.ignoredResult())
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003716 return nullptr;
3717 return generator.emitMove(generator.finalDestination(dst), value.get());
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003718}
3719
caitp@igalia.com0096c962016-09-23 22:24:27 +00003720// ------------------------------ AwaitExprNode --------------------------------
3721
3722RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3723{
3724 RefPtr<RegisterID> arg = generator.newTemporary();
3725 generator.emitNode(arg.get(), argument());
3726 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3727 if (dst == generator.ignoredResult())
3728 return nullptr;
3729 return generator.emitMove(generator.finalDestination(dst), value.get());
3730}
3731
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003732// ------------------------------ ClassDeclNode ---------------------------------
3733
commit-queue@webkit.org678662c2017-06-29 19:34:03 +00003734void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003735{
commit-queue@webkit.org678662c2017-06-29 19:34:03 +00003736 generator.emitNode(dst, m_classDeclaration);
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003737}
3738
3739// ------------------------------ ClassExprNode ---------------------------------
3740
3741RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3742{
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003743 if (!m_name.isNull())
sbarati@apple.combdbba812015-12-19 00:19:41 +00003744 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003745
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003746 RefPtr<RegisterID> superclass;
3747 if (m_classHeritage) {
3748 superclass = generator.newTemporary();
3749 generator.emitNode(superclass.get(), m_classHeritage);
3750 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003751
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003752 RefPtr<RegisterID> constructor;
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003753 bool needsHomeObject = false;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003754
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003755 // FIXME: Make the prototype non-configurable & non-writable.
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003756 if (m_constructorExpression) {
3757 ASSERT(m_constructorExpression->isFuncExprNode());
3758 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata();
3759 metadata->setEcmaName(ecmaName());
3760 metadata->setClassSource(m_classSource);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003761 constructor = generator.emitNode(dst, m_constructorExpression);
gskachkov@gmail.comf92fe152017-06-20 10:27:41 +00003762 needsHomeObject = m_classHeritage || metadata->superBinding() == SuperBinding::Needed;
3763 } else
3764 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003765
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003766 const auto& propertyNames = generator.propertyNames();
3767 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003768
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003769 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003770 RefPtr<RegisterID> protoParent = generator.newTemporary();
3771 generator.emitLoad(protoParent.get(), jsNull());
3772
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003773 RefPtr<RegisterID> tempRegister = generator.newTemporary();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003774
3775 // FIXME: Throw TypeError if it's a generator function.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003776 Ref<Label> superclassIsUndefinedLabel = generator.newLabel();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003777 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
3778
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003779 Ref<Label> superclassIsNullLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003780 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3781
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003782 Ref<Label> superclassIsObjectLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003783 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003784 generator.emitLabel(superclassIsUndefinedLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003785 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3786 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003787 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
3788
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003789 Ref<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003790 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
keith_miller@apple.com02373132016-01-14 20:45:48 +00003791 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_function, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
3792 generator.emitThrowTypeError(ASCIILiteral("The value of the superclass's prototype property is not an object."));
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003793 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
3794
3795 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003796 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003797 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003798 }
3799
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003800 if (needsHomeObject)
3801 emitPutHomeObject(generator, constructor.get(), prototype.get());
3802
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003803 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003804 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +00003805 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003806
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003807 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +00003808 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003809
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003810 if (m_staticMethods)
3811 generator.emitNode(constructor.get(), m_staticMethods);
3812
3813 if (m_instanceMethods)
3814 generator.emitNode(prototype.get(), m_instanceMethods);
3815
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003816 if (!m_name.isNull()) {
3817 Variable classNameVar = generator.variable(m_name);
3818 RELEASE_ASSERT(classNameVar.isResolved());
3819 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
sbarati@apple.come67fd782016-04-19 01:38:30 +00003820 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003821 generator.popLexicalScope(this);
3822 }
3823
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003824 return generator.moveToDestinationIfNeeded(dst, constructor.get());
3825}
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003826
3827// ------------------------------ ImportDeclarationNode -----------------------
3828
3829void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3830{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003831 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003832}
3833
3834// ------------------------------ ExportAllDeclarationNode --------------------
3835
3836void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3837{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003838 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003839}
3840
3841// ------------------------------ ExportDefaultDeclarationNode ----------------
3842
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003843void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003844{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003845 ASSERT(m_declaration);
3846 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003847}
3848
3849// ------------------------------ ExportLocalDeclarationNode ------------------
3850
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003851void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003852{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003853 ASSERT(m_declaration);
3854 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003855}
3856
3857// ------------------------------ ExportNamedDeclarationNode ------------------
3858
3859void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3860{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003861 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003862}
3863
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003864// ------------------------------ DestructuringAssignmentNode -----------------
3865RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
oliver@apple.comd055db62013-10-02 19:11:04 +00003866{
3867 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
3868 return result;
3869 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
3870 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00003871 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003872 return generator.moveToDestinationIfNeeded(dst, initializer.get());
3873}
3874
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003875static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
3876{
3877 ASSERT(defaultValue);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003878 Ref<Label> isNotUndefined = generator.newLabel();
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003879 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
3880 generator.emitNode(maybeUndefined, defaultValue);
3881 generator.emitLabel(isNotUndefined.get());
3882}
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003883
oliver@apple.com47784d62013-10-25 21:31:36 +00003884void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003885{
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003886 RefPtr<RegisterID> iterator = generator.newTemporary();
3887 {
3888 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
3889 CallArguments args(generator, nullptr);
3890 generator.emitMove(args.thisRegister(), rhs);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003891 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003892 }
3893
utatane.tea@gmail.coma5c94332015-06-23 00:51:44 +00003894 if (m_targetPatterns.isEmpty()) {
3895 generator.emitIteratorClose(iterator.get(), this);
3896 return;
3897 }
3898
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003899 RefPtr<RegisterID> done;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003900 for (auto& target : m_targetPatterns) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003901 switch (target.bindingType) {
3902 case BindingType::Elision:
3903 case BindingType::Element: {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003904 Ref<Label> iterationSkipped = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003905 if (!done)
3906 done = generator.newTemporary();
3907 else
3908 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003909
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003910 RefPtr<RegisterID> value = generator.newTemporary();
3911 generator.emitIteratorNext(value.get(), iterator.get(), this);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003912 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003913 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
3914 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003915
3916 {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003917 Ref<Label> valueIsSet = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003918 generator.emitJump(valueIsSet.get());
3919 generator.emitLabel(iterationSkipped.get());
3920 generator.emitLoad(value.get(), jsUndefined());
3921 generator.emitLabel(valueIsSet.get());
3922 }
3923
3924 if (target.bindingType == BindingType::Element) {
3925 if (target.defaultValue)
3926 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
3927 target.pattern->bindValue(generator, value.get());
3928 }
3929 break;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003930 }
3931
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003932 case BindingType::RestElement: {
3933 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
3934
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003935 Ref<Label> iterationDone = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003936 if (!done)
3937 done = generator.newTemporary();
3938 else
3939 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3940
3941 RefPtr<RegisterID> index = generator.newTemporary();
3942 generator.emitLoad(index.get(), jsNumber(0));
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003943 Ref<Label> loopStart = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003944 generator.emitLabel(loopStart.get());
3945
3946 RefPtr<RegisterID> value = generator.newTemporary();
3947 generator.emitIteratorNext(value.get(), iterator.get(), this);
3948 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
3949 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3950 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
3951
3952 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
3953 generator.emitInc(index.get());
3954 generator.emitJump(loopStart.get());
3955
3956 generator.emitLabel(iterationDone.get());
3957 target.pattern->bindValue(generator, array.get());
3958 break;
3959 }
3960 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003961 }
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003962
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003963 Ref<Label> iteratorClosed = generator.newLabel();
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003964 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
3965 generator.emitIteratorClose(iterator.get(), this);
3966 generator.emitLabel(iteratorClosed.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003967}
3968
3969RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
3970{
oliver@apple.comd055db62013-10-02 19:11:04 +00003971 if (!rhs->isSimpleArray())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003972 return nullptr;
3973
3974 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
3975 Vector<ExpressionNode*> elements;
3976 for (; elementNodes; elementNodes = elementNodes->next()) {
3977 ExpressionNode* value = elementNodes->value();
3978 if (value->isSpreadExpression())
3979 return nullptr;
3980 elements.append(value);
3981 }
oliver@apple.com47784d62013-10-25 21:31:36 +00003982
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003983 RefPtr<RegisterID> resultRegister;
3984 if (dst && dst != generator.ignoredResult())
3985 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00003986 if (m_targetPatterns.size() != elements.size())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003987 return nullptr;
oliver@apple.comd055db62013-10-02 19:11:04 +00003988 Vector<RefPtr<RegisterID>> registers;
3989 registers.reserveCapacity(m_targetPatterns.size());
3990 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3991 registers.uncheckedAppend(generator.newTemporary());
3992 generator.emitNode(registers.last().get(), elements[i]);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003993 if (m_targetPatterns[i].defaultValue)
3994 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003995 if (resultRegister)
3996 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003997 }
3998
3999 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00004000 if (m_targetPatterns[i].pattern)
4001 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00004002 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00004003 if (resultRegister)
4004 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00004005 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00004006}
4007
4008void ArrayPatternNode::toString(StringBuilder& builder) const
4009{
4010 builder.append('[');
4011 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00004012 const auto& target = m_targetPatterns[i];
4013
4014 switch (target.bindingType) {
4015 case BindingType::Elision:
oliver@apple.comd055db62013-10-02 19:11:04 +00004016 builder.append(',');
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00004017 break;
4018
4019 case BindingType::Element:
4020 target.pattern->toString(builder);
4021 if (i < m_targetPatterns.size() - 1)
4022 builder.append(',');
4023 break;
4024
4025 case BindingType::RestElement:
commit-queue@webkit.org57101852016-08-12 00:33:47 +00004026 builder.appendLiteral("...");
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00004027 target.pattern->toString(builder);
4028 break;
oliver@apple.comd055db62013-10-02 19:11:04 +00004029 }
oliver@apple.comd055db62013-10-02 19:11:04 +00004030 }
4031 builder.append(']');
4032}
4033
4034void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4035{
4036 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.comc497d152015-07-17 18:48:30 +00004037 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
oliver@apple.comd055db62013-10-02 19:11:04 +00004038 node->collectBoundIdentifiers(identifiers);
4039 }
4040}
4041
4042void ObjectPatternNode::toString(StringBuilder& builder) const
4043{
4044 builder.append('{');
4045 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00004046 if (m_targetPatterns[i].wasString)
akling@apple.coma9904fb2015-05-08 08:44:23 +00004047 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00004048 else
oliver@apple.comd055db62013-10-02 19:11:04 +00004049 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00004050 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00004051 m_targetPatterns[i].pattern->toString(builder);
4052 if (i < m_targetPatterns.size() - 1)
4053 builder.append(',');
4054 }
4055 builder.append('}');
4056}
4057
oliver@apple.com47784d62013-10-25 21:31:36 +00004058void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00004059{
commit-queue@webkit.org4d3e0c22015-12-01 20:11:20 +00004060 generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
mark.lam@apple.comcf0bf6c2017-05-16 00:21:59 +00004061
ticaiolima@gmail.com9df92eb2017-06-28 03:05:47 +00004062 RefPtr<RegisterID> excludedList;
4063 IdentifierSet excludedSet;
4064 RefPtr<RegisterID> addMethod;
4065 if (m_containsRestElement && m_containsComputedProperty) {
4066 auto var = generator.variable(generator.propertyNames().builtinNames().SetPrivateName());
4067
4068 RefPtr<RegisterID> scope = generator.newTemporary();
4069 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
4070 RefPtr<RegisterID> setConstructor = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4071
4072 CallArguments args(generator, nullptr, 0);
4073 excludedList = generator.emitConstruct(generator.newTemporary(), setConstructor.get(), setConstructor.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
4074
4075 addMethod = generator.emitGetById(generator.newTemporary(), excludedList.get(), generator.propertyNames().builtinNames().addPrivateName());
4076 }
4077
4078 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
4079 const auto& target = m_targetPatterns[i];
4080 if (target.bindingType == BindingType::Element) {
4081 RefPtr<RegisterID> temp = generator.newTemporary();
4082 RefPtr<RegisterID> propertyName;
4083 if (!target.propertyExpression) {
4084 std::optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
4085 if (!optionalIndex)
4086 generator.emitGetById(temp.get(), rhs, target.propertyName);
4087 else {
4088 RefPtr<RegisterID> propertyIndex = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
4089 generator.emitGetByVal(temp.get(), rhs, propertyIndex.get());
4090 }
4091 } else {
4092 propertyName = generator.emitNodeForProperty(target.propertyExpression);
4093 generator.emitGetByVal(temp.get(), rhs, propertyName.get());
4094 }
4095
4096 if (m_containsRestElement) {
4097 if (m_containsComputedProperty) {
4098 if (!target.propertyExpression)
4099 propertyName = generator.emitLoad(nullptr, target.propertyName);
4100
4101 CallArguments args(generator, nullptr, 1);
4102 generator.emitMove(args.thisRegister(), excludedList.get());
4103 generator.emitMove(args.argumentRegister(0), propertyName.get());
4104 generator.emitCall(generator.newTemporary(), addMethod.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4105 } else
4106 excludedSet.add(target.propertyName.impl());
4107 }
4108
4109 if (target.defaultValue)
4110 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
4111 target.pattern->bindValue(generator, temp.get());
4112 } else {
4113 ASSERT(target.bindingType == BindingType::RestElement);
4114 ASSERT(i == m_targetPatterns.size() - 1);
4115 RefPtr<RegisterID> newObject = generator.emitNewObject(generator.newTemporary());
4116
4117 // load and call @copyDataProperties
4118 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
4119
4120 RefPtr<RegisterID> scope = generator.newTemporary();
4121 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
4122 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4123
4124 CallArguments args(generator, nullptr, 3);
4125 generator.emitLoad(args.thisRegister(), jsUndefined());
4126 generator.emitMove(args.argumentRegister(0), newObject.get());
4127 generator.emitMove(args.argumentRegister(1), rhs);
4128 if (m_containsComputedProperty)
4129 generator.emitMove(args.argumentRegister(2), excludedList.get());
4130 else {
4131 RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
4132 generator.emitMove(args.argumentRegister(2), excludedSetReg.get());
4133 }
4134
4135 RefPtr<RegisterID> result = generator.newTemporary();
4136 generator.emitCall(result.get(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4137 target.pattern->bindValue(generator, result.get());
4138 }
oliver@apple.comd055db62013-10-02 19:11:04 +00004139 }
4140}
4141
4142void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4143{
4144 for (size_t i = 0; i < m_targetPatterns.size(); i++)
4145 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
4146}
4147
oliver@apple.com47784d62013-10-25 21:31:36 +00004148void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00004149{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004150 Variable var = generator.variable(m_boundProperty);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004151 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004152 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004153 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4154 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004155 if (isReadOnly) {
4156 generator.emitReadOnlyExceptionIfNeeded(var);
4157 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00004158 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004159 generator.emitMove(local, value);
sbarati@apple.com180ae512017-07-06 18:43:41 +00004160 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00004161 generator.emitProfileType(local, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004162 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004163 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00004164 return;
4165 }
4166 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00004167 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00004168 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00004169 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004170 if (m_bindingContext == AssignmentContext::AssignmentExpression)
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00004171 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004172 if (isReadOnly) {
4173 generator.emitReadOnlyExceptionIfNeeded(var);
4174 return;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004175 }
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00004176 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00004177 generator.emitProfileType(value, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004178 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004179 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00004180 return;
4181}
4182
4183void BindingNode::toString(StringBuilder& builder) const
4184{
4185 builder.append(m_boundProperty.string());
4186}
4187
4188void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4189{
4190 identifiers.append(m_boundProperty);
4191}
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004192
4193void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
4194{
4195}
4196
4197void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
4198{
4199 if (m_assignmentTarget->isResolveNode()) {
4200 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
4201 Variable var = generator.variable(lhs->identifier());
4202 bool isReadOnly = var.isReadOnly();
4203 if (RegisterID* local = var.local()) {
4204 generator.emitTDZCheckIfNecessary(var, local, nullptr);
4205
4206 if (isReadOnly)
4207 generator.emitReadOnlyExceptionIfNeeded(var);
4208 else {
4209 generator.invalidateForInContextForLocal(local);
4210 generator.moveToDestinationIfNeeded(local, value);
4211 generator.emitProfileType(local, divotStart(), divotEnd());
4212 }
4213 return;
4214 }
4215 if (generator.isStrictMode())
4216 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4217 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
4218 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
4219 if (isReadOnly) {
4220 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
4221 if (threwException)
4222 return;
4223 }
4224 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4225 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00004226 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004227 generator.emitProfileType(value, var, divotStart(), divotEnd());
4228 }
4229 } else if (m_assignmentTarget->isDotAccessorNode()) {
4230 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
4231 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4232 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00004233 if (lhs->base()->isSuperNode()) {
4234 RefPtr<RegisterID> thisValue = generator.ensureThis();
4235 generator.emitPutById(base.get(), thisValue.get(), lhs->identifier(), value);
4236 } else
4237 generator.emitPutById(base.get(), lhs->identifier(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004238 generator.emitProfileType(value, divotStart(), divotEnd());
4239 } else if (m_assignmentTarget->isBracketAccessorNode()) {
4240 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
4241 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
utatane.tea@gmail.com1456b252017-05-22 05:33:47 +00004242 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSideForProperty(lhs->subscript(), true, false);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004243 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00004244 if (lhs->base()->isSuperNode()) {
4245 RefPtr<RegisterID> thisValue = generator.ensureThis();
4246 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
4247 } else
4248 generator.emitPutByVal(base.get(), property.get(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004249 generator.emitProfileType(value, divotStart(), divotEnd());
4250 }
4251}
4252
4253void AssignmentElementNode::toString(StringBuilder& builder) const
4254{
4255 if (m_assignmentTarget->isResolveNode())
4256 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
4257}
4258
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004259void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4260{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004261 m_pattern->collectBoundIdentifiers(identifiers);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004262}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004263
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004264void RestParameterNode::toString(StringBuilder& builder) const
4265{
commit-queue@webkit.org57101852016-08-12 00:33:47 +00004266 builder.appendLiteral("...");
sbarati@apple.com6a686122016-08-03 07:50:40 +00004267 m_pattern->toString(builder);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004268}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004269
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004270void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
4271{
4272 RELEASE_ASSERT_NOT_REACHED();
4273}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004274
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004275void RestParameterNode::emit(BytecodeGenerator& generator)
4276{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004277 RefPtr<RegisterID> temp = generator.newTemporary();
4278 generator.emitRestParameter(temp.get(), m_numParametersToSkip);
4279 m_pattern->bindValue(generator, temp.get());
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004280}
4281
4282
oliver@apple.com72f8a822013-10-17 01:02:34 +00004283RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4284{
4285 RELEASE_ASSERT_NOT_REACHED();
4286 return 0;
4287}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00004288
ticaiolima@gmail.comf62044c2017-07-13 07:11:45 +00004289RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4290{
4291 RefPtr<RegisterID> src = generator.newTemporary();
4292 generator.emitNode(src.get(), m_expression);
4293
4294 // load and call @copyDataPropertiesNoExclusions
4295 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesNoExclusionsPrivateName());
4296
4297 RefPtr<RegisterID> scope = generator.newTemporary();
4298 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
4299 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4300
4301 CallArguments args(generator, nullptr, 2);
4302 generator.emitLoad(args.thisRegister(), jsUndefined());
4303 generator.emitMove(args.argumentRegister(0), dst);
4304 generator.emitMove(args.argumentRegister(1), src.get());
4305
4306 generator.emitCall(generator.newTemporary(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4307
4308 return dst;
4309}
4310
mjs@apple.comaed3cef2009-12-09 01:29:52 +00004311} // namespace JSC