blob: f3e5557acf2411306b5f1c15d3305cc6c346f9d0 [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>
commit-queue@webkit.org2162b032017-03-10 02:00:33 +000044#include <wtf/HashSet.h>
mjs@apple.comaed3cef2009-12-09 01:29:52 +000045#include <wtf/Threading.h>
joepeck@webkit.org7e07f392016-09-22 18:59:47 +000046#include <wtf/text/StringBuilder.h>
commit-queue@webkit.org2162b032017-03-10 02:00:33 +000047#include <wtf/text/UniquedStringImpl.h>
mjs@apple.comaed3cef2009-12-09 01:29:52 +000048
49using namespace WTF;
50
51namespace JSC {
52
53/*
54 Details of the emitBytecode function.
55
56 Return value: The register holding the production's value.
57 dst: An optional parameter specifying the most efficient destination at
58 which to store the production's value. The callee must honor dst.
59
60 The dst argument provides for a crude form of copy propagation. For example,
61
62 x = 1
63
64 becomes
65
66 load r[x], 1
67
68 instead of
69
70 load r0, 1
71 mov r[x], r0
72
73 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
74*/
75
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +000076void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +000077{
78 RegisterID* result = generator.emitNode(this);
79 if (fallThroughMode == FallThroughMeansTrue)
80 generator.emitJumpIfFalse(result, falseTarget);
81 else
82 generator.emitJumpIfTrue(result, trueTarget);
83}
84
mjs@apple.comaed3cef2009-12-09 01:29:52 +000085// ------------------------------ ThrowableExpressionData --------------------------------
86
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000087RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000088{
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +000089 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com4920ae92010-11-12 03:06:07 +000090 generator.emitThrowReferenceError(message);
91 return generator.newTemporary();
mjs@apple.comaed3cef2009-12-09 01:29:52 +000092}
93
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000094// ------------------------------ ConstantNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +000095
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +000096void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000097{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000098 TriState value = jsValue(generator).pureToBoolean();
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +000099
100 if (UNLIKELY(needsDebugHook())) {
101 if (value != MixedTriState)
102 generator.emitDebugHook(this);
103 }
104
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000105 if (value == MixedTriState)
106 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
107 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
108 generator.emitJump(trueTarget);
109 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
110 generator.emitJump(falseTarget);
111
112 // All other cases are unconditional fall-throughs, like "if (true)".
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000113}
114
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000115RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000116{
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000117 if (dst == generator.ignoredResult())
118 return 0;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000119 return generator.emitLoad(dst, jsValue(generator));
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000120}
121
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000122JSValue StringNode::jsValue(BytecodeGenerator& generator) const
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000123{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000124 return generator.addStringConstant(m_value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000125}
126
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000127// ------------------------------ NumberNode ----------------------------------
128
129RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
130{
131 if (dst == generator.ignoredResult())
132 return nullptr;
133 return generator.emitLoad(dst, jsValue(generator), isIntegerNode() ? SourceCodeRepresentation::Integer : SourceCodeRepresentation::Double);
134}
135
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000136// ------------------------------ RegExpNode -----------------------------------
137
138RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
139{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000140 if (dst == generator.ignoredResult())
141 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000142 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 +0000143}
144
145// ------------------------------ ThisNode -------------------------------------
146
147RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
148{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000149 generator.ensureThis();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000150 if (dst == generator.ignoredResult())
151 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000152
153 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000154 static const unsigned thisLength = 4;
155 generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000156 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000157}
158
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000159// ------------------------------ SuperNode -------------------------------------
160
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000161static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000162{
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000163 if (generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {
164 RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000165 return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().builtinNames().homeObjectPrivateName());
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000166 }
167
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000168 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000169 callee.setIndex(CallFrameSlot::callee);
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000170 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().builtinNames().homeObjectPrivateName());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000171}
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000172
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000173static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
174{
175 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000176 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
177}
178
sbarati@apple.com23315d62016-05-09 20:17:23 +0000179static RegisterID* emitGetSuperFunctionForConstruct(BytecodeGenerator& generator)
180{
181 if (generator.isDerivedConstructorContext())
182 return generator.emitGetById(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(), generator.propertyNames().underscoreProto);
183
184 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000185 callee.setIndex(CallFrameSlot::callee);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000186 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().underscoreProto);
187}
188
189RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
190{
191 RegisterID* result = emitSuperBaseForCallee(generator);
192 return generator.moveToDestinationIfNeeded(generator.finalDestination(dst), result);
193}
194
utatane.tea@gmail.com5e639122017-01-09 22:02:47 +0000195// ------------------------------ ImportNode -------------------------------------
196
197RegisterID* ImportNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
198{
199 RefPtr<RegisterID> importModule = generator.emitGetGlobalPrivate(generator.newTemporary(), generator.propertyNames().builtinNames().importModulePrivateName());
200 CallArguments arguments(generator, nullptr, 1);
201 generator.emitLoad(arguments.thisRegister(), jsUndefined());
202 generator.emitNode(arguments.argumentRegister(0), m_expr);
203 return generator.emitCall(generator.finalDestination(dst, importModule.get()), importModule.get(), NoExpectedFunction, arguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
204}
205
commit-queue@webkit.org17f99e42015-07-21 18:18:42 +0000206// ------------------------------ NewTargetNode ----------------------------------
207
208RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
209{
210 if (dst == generator.ignoredResult())
211 return nullptr;
212
213 return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
214}
215
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000216// ------------------------------ ResolveNode ----------------------------------
217
218bool ResolveNode::isPure(BytecodeGenerator& generator) const
219{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000220 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000221}
222
223RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
224{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000225 Variable var = generator.variable(m_ident);
226 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000227 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000228 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000229 return nullptr;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000230
231 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000232 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000233 }
234
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000235 JSTextPosition divot = m_start + m_ident.length();
236 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000237 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000238 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000239 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000240 generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000241 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000242 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000243}
244
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000245// ------------------------------ TemplateStringNode -----------------------------------
246
247RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
248{
249 if (dst == generator.ignoredResult())
250 return nullptr;
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000251 ASSERT(cooked());
252 return generator.emitLoad(dst, JSValue(generator.addStringConstant(*cooked())));
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000253}
254
255// ------------------------------ TemplateLiteralNode -----------------------------------
256
257RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
258{
259 if (!m_templateExpressions) {
260 TemplateStringNode* templateString = m_templateStrings->value();
261 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
262 return generator.emitNode(dst, templateString);
263 }
264
265 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
266
267 TemplateStringListNode* templateString = m_templateStrings;
268 TemplateExpressionListNode* templateExpression = m_templateExpressions;
269 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
270 // Evaluate TemplateString.
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000271 ASSERT(templateString->value()->cooked());
272 if (!templateString->value()->cooked()->isEmpty()) {
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000273 temporaryRegisters.append(generator.newTemporary());
274 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
275 }
276
277 // Evaluate Expression.
278 temporaryRegisters.append(generator.newTemporary());
279 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
280 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
281 }
282
283 // Evaluate tail TemplateString.
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000284 ASSERT(templateString->value()->cooked());
285 if (!templateString->value()->cooked()->isEmpty()) {
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000286 temporaryRegisters.append(generator.newTemporary());
287 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
288 }
289
oliver@apple.com1aec7c72016-06-13 23:17:00 +0000290 if (temporaryRegisters.size() == 1)
291 return generator.emitToString(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get());
292
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000293 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
294}
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000295
296// ------------------------------ TaggedTemplateNode -----------------------------------
297
298RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
299{
300 ExpectedFunction expectedFunction = NoExpectedFunction;
301 RefPtr<RegisterID> tag = nullptr;
302 RefPtr<RegisterID> base = nullptr;
303 if (!m_tag->isLocation()) {
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000304 tag = generator.newTemporary();
305 tag = generator.emitNode(tag.get(), m_tag);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000306 } else if (m_tag->isResolveNode()) {
307 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
308 const Identifier& identifier = resolve->identifier();
309 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
310
311 Variable var = generator.variable(identifier);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000312 if (RegisterID* local = var.local()) {
313 generator.emitTDZCheckIfNecessary(var, local, nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000314 tag = generator.emitMove(generator.newTemporary(), local);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000315 } else {
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000316 tag = generator.newTemporary();
317 base = generator.newTemporary();
318
319 JSTextPosition newDivot = divotStart() + identifier.length();
320 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
321 generator.moveToDestinationIfNeeded(base.get(), generator.emitResolveScope(base.get(), var));
322 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000323 generator.emitTDZCheckIfNecessary(var, tag.get(), nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000324 }
325 } else if (m_tag->isBracketAccessorNode()) {
326 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000327 base = generator.newTemporary();
328 base = generator.emitNode(base.get(), bracket->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000329 RefPtr<RegisterID> property = generator.emitNode(bracket->subscript());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000330 if (bracket->base()->isSuperNode()) {
331 RefPtr<RegisterID> thisValue = generator.ensureThis();
332 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
333 } else
334 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000335 } else {
336 ASSERT(m_tag->isDotAccessorNode());
337 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000338 base = generator.newTemporary();
339 base = generator.emitNode(base.get(), dot->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000340 if (dot->base()->isSuperNode()) {
341 RefPtr<RegisterID> thisValue = generator.ensureThis();
342 tag = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), dot->identifier());
343 } else
344 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000345 }
346
utatane.tea@gmail.com6cd55812017-04-05 07:09:41 +0000347 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(nullptr, this);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000348
349 unsigned expressionsCount = 0;
350 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
351 ++expressionsCount;
352
353 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
354 if (base)
355 generator.emitMove(callArguments.thisRegister(), base.get());
356 else
357 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
358
359 unsigned argumentIndex = 0;
360 generator.emitMove(callArguments.argumentRegister(argumentIndex++), templateObject.get());
361 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
362 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
363
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000364 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 +0000365}
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000366
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000367// ------------------------------ ArrayNode ------------------------------------
368
369RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
370{
371 // FIXME: Should we put all of this code into emitNewArray?
372
373 unsigned length = 0;
374 ElementNode* firstPutElement;
375 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000376 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000377 break;
378 ++length;
379 }
380
381 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000382 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000383
sbarati@apple.com99ed4792016-11-12 02:58:11 +0000384 if (firstPutElement && firstPutElement->value()->isSpreadExpression()) {
385 bool hasElision = false;
386 for (ElementNode* node = m_element; node; node = node->next()) {
387 if (!!node->elision()) {
388 hasElision = true;
389 break;
390 }
391 }
392 if (!!m_elision)
393 hasElision = true;
394
395 if (!hasElision)
396 return generator.emitNewArrayWithSpread(generator.finalDestination(dst), m_element);
397 }
398
oliver@apple.coma991d692011-06-14 23:39:25 +0000399 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000400 ElementNode* n = firstPutElement;
401 for (; n; n = n->next()) {
402 if (n->value()->isSpreadExpression())
403 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000404 RegisterID* value = generator.emitNode(n->value());
405 length += n->elision();
406 generator.emitPutByIndex(array.get(), length++, value);
407 }
408
409 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000410 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000411 generator.emitPutById(array.get(), generator.propertyNames().length, value);
412 }
413
414 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000415
416handleSpread:
417 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
annulen@yandex.ru0226e412017-04-21 03:38:16 +0000418 auto spreader = [array, index](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com72f8a822013-10-17 01:02:34 +0000419 {
oliver@apple.come050d642013-10-19 00:09:28 +0000420 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000421 generator.emitInc(index.get());
422 };
423 for (; n; n = n->next()) {
424 if (n->elision())
425 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
426 if (n->value()->isSpreadExpression()) {
427 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
428 generator.emitEnumeration(spread, spread->expression(), spreader);
429 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000430 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000431 generator.emitInc(index.get());
432 }
433 }
434
435 if (m_elision) {
436 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
437 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
438 }
439 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000440}
441
442bool ArrayNode::isSimpleArray() const
443{
444 if (m_elision || m_optional)
445 return false;
446 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
447 if (ptr->elision())
448 return false;
commit-queue@webkit.org1a78b432016-09-15 01:14:45 +0000449 if (ptr->value()->isSpreadExpression())
450 return false;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000451 }
452 return true;
453}
454
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000455ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000456{
457 ASSERT(!m_elision && !m_optional);
458 ElementNode* ptr = m_element;
459 if (!ptr)
460 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000461 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000462 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000463 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000464 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000465 ArgumentListNode* tail = head;
466 ptr = ptr->next();
467 for (; ptr; ptr = ptr->next()) {
468 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000469 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000470 }
471 return head;
472}
473
474// ------------------------------ ObjectLiteralNode ----------------------------
475
476RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
477{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000478 if (!m_list) {
479 if (dst == generator.ignoredResult())
480 return 0;
481 return generator.emitNewObject(generator.finalDestination(dst));
482 }
483 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
484 generator.emitNode(newObj.get(), m_list);
485 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000486}
487
488// ------------------------------ PropertyListNode -----------------------------
489
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000490static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
491{
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000492 generator.emitPutById(function, generator.propertyNames().builtinNames().homeObjectPrivateName(), homeObject);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000493}
494
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000495RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
496{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000497 // Fast case: this loop just handles regular value properties.
498 PropertyListNode* p = this;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000499 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000500 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000501
502 // Were there any get/set properties?
503 if (p) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000504 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
505 // a computed property, just emit everything as that may override previous values.
506 bool hasComputedProperty = false;
507
barraclough@apple.com09a55682012-01-30 18:28:39 +0000508 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000509 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000510 GetterSetterMap map;
511
512 // Build a map, pairing get/set values together.
513 for (PropertyListNode* q = p; q; q = q->m_next) {
514 PropertyNode* node = q->m_node;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000515 if (node->m_type & PropertyNode::Computed) {
516 hasComputedProperty = true;
517 break;
518 }
commit-queue@webkit.org97475e72017-03-16 12:58:14 +0000519 if (node->m_type & PropertyNode::Constant || node->m_type & PropertyNode::Spread)
barraclough@apple.com09a55682012-01-30 18:28:39 +0000520 continue;
521
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000522 // Duplicates are possible.
523 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
oliver@apple.com72d38322013-10-21 19:23:24 +0000524 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000525 if (!result.isNewEntry) {
526 if (result.iterator->value.first->m_type == node->m_type)
527 result.iterator->value.first = node;
528 else
529 result.iterator->value.second = node;
530 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000531 }
532
533 // Iterate over the remaining properties in the list.
534 for (; p; p = p->m_next) {
535 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000536
537 // Handle regular values.
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000538 if (node->m_type & PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000539 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000540 continue;
commit-queue@webkit.org97475e72017-03-16 12:58:14 +0000541 } else if (node->m_type & PropertyNode::Spread) {
542 generator.emitNode(dst, node->m_assign);
543 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000544 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000545
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000546 RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000547 bool needsSuperBinding = node->needsSuperBinding();
548 if (needsSuperBinding)
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000549 emitPutHomeObject(generator, value.get(), dst);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000550
551 unsigned attributes = node->isClassProperty() ? (Accessor | DontEnum) : Accessor;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000552
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000553 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
554
555 // This is a get/set property which may be overridden by a computed property later.
556 if (hasComputedProperty) {
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000557 // Computed accessors.
558 if (node->m_type & PropertyNode::Computed) {
559 RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000560 generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000561 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000562 generator.emitPutGetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000563 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000564 generator.emitPutSetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000565 continue;
566 }
567
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000568 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000569 generator.emitPutGetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000570 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000571 generator.emitPutSetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000572 continue;
573 }
574
575 // This is a get/set property pair.
oliver@apple.com72d38322013-10-21 19:23:24 +0000576 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000577 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000578 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000579
580 // Was this already generated as a part of its partner?
581 if (pair.second == node)
582 continue;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000583
barraclough@apple.com09a55682012-01-30 18:28:39 +0000584 // Generate the paired node now.
585 RefPtr<RegisterID> getterReg;
586 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000587 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000588
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000589 if (node->m_type & PropertyNode::Getter) {
barraclough@apple.com09a55682012-01-30 18:28:39 +0000590 getterReg = value;
591 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000592 ASSERT(pair.second->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000593 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000594 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000595 } else {
596 setterReg = generator.newTemporary();
597 generator.emitLoad(setterReg.get(), jsUndefined());
598 }
599 } else {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000600 ASSERT(node->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000601 setterReg = value;
602 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000603 ASSERT(pair.second->m_type & PropertyNode::Getter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000604 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000605 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000606 } else {
607 getterReg = generator.newTemporary();
608 generator.emitLoad(getterReg.get(), jsUndefined());
609 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000610 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000611
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000612 ASSERT(!pair.second || needsSuperBinding == pair.second->needsSuperBinding());
613 if (needsSuperBinding && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000614 emitPutHomeObject(generator, secondReg, dst);
615
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000616 generator.emitPutGetterSetter(dst, *node->name(), attributes, getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000617 }
618 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000619
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000620 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000621}
622
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000623void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
624{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000625 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000626 if (node.needsSuperBinding())
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000627 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000628
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000629 if (node.isClassProperty()) {
630 ASSERT(node.needsSuperBinding());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000631 RefPtr<RegisterID> propertyNameRegister;
632 if (node.name())
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000633 propertyNameRegister = generator.emitLoad(nullptr, *node.name());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000634 else
635 propertyNameRegister = generator.emitNode(node.m_expression);
636
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000637 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +0000638 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000639 return;
640 }
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000641 if (const auto* identifier = node.name()) {
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000642 std::optional<uint32_t> optionalIndex = parseIndex(*identifier);
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000643 if (!optionalIndex) {
644 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
645 return;
646 }
647
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000648 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000649 generator.emitDirectPutByVal(newObj, index.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000650 return;
651 }
652 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000653 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000654 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000655}
656
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000657// ------------------------------ BracketAccessorNode --------------------------------
658
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000659static bool isNonIndexStringElement(ExpressionNode& element)
660{
661 return element.isString() && !parseIndex(static_cast<StringNode&>(element).value());
662}
663
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000664RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
665{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000666 if (m_base->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000667 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
668 RefPtr<RegisterID> thisValue = generator.ensureThis();
669 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000670
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000671 if (isNonIndexStringElement(*m_subscript)) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000672 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000673 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000674 generator.emitGetById(finalDest.get(), superBase.get(), thisValue.get(), id);
675 } else {
676 RefPtr<RegisterID> subscript = generator.emitNode(m_subscript);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000677 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000678 generator.emitGetByVal(finalDest.get(), superBase.get(), thisValue.get(), subscript.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000679 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000680
sbarati@apple.com23315d62016-05-09 20:17:23 +0000681 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
682 return finalDest.get();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000683 }
684
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000685 RegisterID* ret;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000686 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000687
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000688 if (isNonIndexStringElement(*m_subscript)) {
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000689 RefPtr<RegisterID> base = generator.emitNode(m_base);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000690 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000691 ret = generator.emitGetById(finalDest.get(), base.get(), static_cast<StringNode*>(m_subscript)->value());
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000692 } else {
693 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
694 RegisterID* property = generator.emitNode(m_subscript);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000695 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000696 ret = generator.emitGetByVal(finalDest.get(), base.get(), property);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000697 }
698
sbarati@apple.com23315d62016-05-09 20:17:23 +0000699 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000700 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000701}
702
703// ------------------------------ DotAccessorNode --------------------------------
704
705RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
706{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000707 bool baseIsSuper = m_base->isSuperNode();
708 RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000709 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000710 RegisterID* finalDest = generator.finalDestination(dst);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000711 RegisterID* ret;
712 if (baseIsSuper) {
713 RefPtr<RegisterID> thisValue = generator.ensureThis();
714 ret = generator.emitGetById(finalDest, base.get(), thisValue.get(), m_ident);
715 } else
716 ret = generator.emitGetById(finalDest, base.get(), m_ident);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000717 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000718 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000719}
720
721// ------------------------------ ArgumentListNode -----------------------------
722
723RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
724{
725 ASSERT(m_expr);
726 return generator.emitNode(dst, m_expr);
727}
728
729// ------------------------------ NewExprNode ----------------------------------
730
731RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
732{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000733 ExpectedFunction expectedFunction;
734 if (m_expr->isResolveNode())
735 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
736 else
737 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000738 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000739 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000740 CallArguments callArguments(generator, m_args);
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000741 generator.emitMove(callArguments.thisRegister(), func.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000742 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000743}
744
oliver@apple.com72f8a822013-10-17 01:02:34 +0000745CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000746 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000747 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000748{
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000749 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000750 if (argumentsNode) {
751 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
752 ++argumentCountIncludingThis;
753 }
754
755 m_argv.grow(argumentCountIncludingThis);
756 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
757 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000758 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 +0000759 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000760
761 // We need to ensure that the frame size is stack-aligned
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000762 while ((CallFrame::headerSizeInRegisters + m_argv.size()) % stackAlignmentRegisters()) {
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000763 m_argv.insert(0, generator.newTemporary());
764 m_padding++;
765 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000766
767 while (stackOffset() % stackAlignmentRegisters()) {
768 m_argv.insert(0, generator.newTemporary());
769 m_padding++;
770 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000771}
772
773// ------------------------------ EvalFunctionCallNode ----------------------------------
774
775RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
776{
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000777 // We need try to load 'this' before call eval in constructor, because 'this' can created by 'super' in some of the arrow function
778 // var A = class A {
779 // constructor () { this.id = 'A'; }
780 // }
781 //
782 // var B = class B extend A {
783 // constructor () {
784 // var arrow = () => super();
785 // arrow();
786 // eval("this.id = 'B'");
787 // }
788 // }
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000789 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000790 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
791
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000792 Variable var = generator.variable(generator.propertyNames().eval);
793 if (RegisterID* local = var.local()) {
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000794 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000795 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000796 CallArguments callArguments(generator, m_args);
797 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000798 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
oliver@apple.com58c86752013-07-25 04:02:40 +0000799 }
800
801 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000802 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000803 JSTextPosition newDivot = divotStart() + 4;
804 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000805 generator.moveToDestinationIfNeeded(
806 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000807 generator.emitResolveScope(callArguments.thisRegister(), var));
808 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000809 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000810 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000811}
812
813// ------------------------------ FunctionCallValueNode ----------------------------------
814
815RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
816{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000817 if (m_expr->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000818 RefPtr<RegisterID> func = emitGetSuperFunctionForConstruct(generator);
819 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
820 CallArguments callArguments(generator, m_args);
821
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000822 ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000823 ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000824 generator.emitMove(callArguments.thisRegister(), generator.newTarget());
825 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000826
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000827 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000828 bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
829
830 if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction()))
831 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
832
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +0000833 Ref<Label> thisIsEmptyLabel = generator.newLabel();
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000834 generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get());
835 generator.emitThrowReferenceError(ASCIILiteral("'super()' can't be called more than once in a constructor."));
836 generator.emitLabel(thisIsEmptyLabel.get());
837
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000838 generator.emitMove(generator.thisRegister(), ret);
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000839
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000840 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor)
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000841 generator.emitPutThisToArrowFunctionContextScope();
commit-queue@webkit.orgabdc6172016-02-24 20:46:44 +0000842
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000843 return ret;
844 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000845 RefPtr<RegisterID> func = generator.emitNode(m_expr);
846 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
847 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000848 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000849 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000850 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000851 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000852}
853
854// ------------------------------ FunctionCallResolveNode ----------------------------------
855
856RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
857{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000858 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000859
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000860 Variable var = generator.variable(m_ident);
861 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000862 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000863 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000864 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000865 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000866 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000867 // This passes NoExpectedFunction because we expect that if the function is in a
868 // local variable, then it's not one of our built-in constructors.
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000869 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000870 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000871 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000872 }
873
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000874 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000875 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000876 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000877
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000878 JSTextPosition newDivot = divotStart() + m_ident.length();
879 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000880 generator.moveToDestinationIfNeeded(
881 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000882 generator.emitResolveScope(callArguments.thisRegister(), var));
883 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000884 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000885 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000886 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000887 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000888}
889
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000890// ------------------------------ BytecodeIntrinsicNode ----------------------------------
891
892RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
893{
894 return (this->*m_emitter)(generator, dst);
895}
896
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +0000897RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argument(BytecodeGenerator& generator, RegisterID* dst)
898{
899 ArgumentListNode* node = m_args->m_listNode;
900 ASSERT(node->m_expr->isNumber());
901 double value = static_cast<NumberNode*>(node->m_expr)->value();
902 int32_t index = static_cast<int32_t>(value);
903 ASSERT(value == index);
904 ASSERT(index >= 0);
905 ASSERT(!node->m_next);
906
907 // The body functions of generator and async have different mechanism for arguments.
908 ASSERT(generator.parseMode() != SourceParseMode::GeneratorBodyMode);
909 ASSERT(!isAsyncFunctionBodyParseMode(generator.parseMode()));
910
911 return generator.emitGetArgument(generator.finalDestination(dst), index);
912}
913
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +0000914RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator& generator, RegisterID* dst)
915{
916 ASSERT(!m_args->m_listNode);
917
918 return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
919}
920
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +0000921RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator& generator, RegisterID* dst)
922{
923#ifndef NDEBUG
924 ArgumentListNode* node = m_args->m_listNode;
925 RefPtr<RegisterID> condition = generator.emitNode(node);
926 generator.emitAssert(condition.get(), node->firstLine());
927 return dst;
928#else
929 UNUSED_PARAM(generator);
930 return dst;
931#endif
932}
933
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000934RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
935{
936 ArgumentListNode* node = m_args->m_listNode;
937 RefPtr<RegisterID> base = generator.emitNode(node);
938 node = node->m_next;
939 RefPtr<RegisterID> index = generator.emitNode(node);
940 node = node->m_next;
941 RefPtr<RegisterID> value = generator.emitNode(node);
942
943 ASSERT(!node->m_next);
944
945 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
946}
947
keith_miller@apple.come497e202016-06-13 21:05:36 +0000948RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator& generator, RegisterID* dst)
949{
950 ArgumentListNode* node = m_args->m_listNode;
951 RefPtr<RegisterID> function = generator.emitNode(node);
952 node = node->m_next;
953 RefPtr<RegisterID> thisRegister = generator.emitNode(node);
954 ASSERT(!node->m_next);
955
956 RefPtr<RegisterID> finalDst = generator.finalDestination(dst);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000957 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 +0000958}
959
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000960RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwTypeError(BytecodeGenerator& generator, RegisterID* dst)
961{
962 ArgumentListNode* node = m_args->m_listNode;
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000963 ASSERT(!node->m_next);
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +0000964 if (node->m_expr->isString()) {
965 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
966 generator.emitThrowTypeError(ident);
967 } else {
968 RefPtr<RegisterID> message = generator.emitNode(node);
969 generator.emitThrowStaticError(ErrorType::TypeError, message.get());
970 }
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000971 return dst;
972}
973
974RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwRangeError(BytecodeGenerator& generator, RegisterID* dst)
975{
976 ArgumentListNode* node = m_args->m_listNode;
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000977 ASSERT(!node->m_next);
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +0000978 if (node->m_expr->isString()) {
979 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
980 generator.emitThrowRangeError(ident);
981 } else {
982 RefPtr<RegisterID> message = generator.emitNode(node);
983 generator.emitThrowStaticError(ErrorType::RangeError, message.get());
984 }
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000985
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000986 return dst;
987}
988
989RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwOutOfMemoryError(BytecodeGenerator& generator, RegisterID* dst)
990{
991 ASSERT(!m_args->m_listNode);
992
993 generator.emitThrowOutOfMemoryError();
994 return dst;
995}
996
keith_miller@apple.com8844d302016-04-07 19:38:00 +0000997RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
998{
999 ArgumentListNode* node = m_args->m_listNode;
1000 RefPtr<RegisterID> base = generator.emitNode(node);
1001 node = node->m_next;
1002
1003 // Since this is a builtin we expect the creator to use a string literal as the second argument.
1004 ASSERT(node->m_expr->isString());
1005 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1006 ASSERT(!node->m_next);
1007
keith_miller@apple.come497e202016-06-13 21:05:36 +00001008 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
1009 return generator.emitTryGetById(finalDest.get(), base.get(), ident);
keith_miller@apple.com8844d302016-04-07 19:38:00 +00001010}
1011
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001012RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toNumber(BytecodeGenerator& generator, RegisterID* dst)
1013{
1014 ArgumentListNode* node = m_args->m_listNode;
1015 RefPtr<RegisterID> src = generator.emitNode(node);
1016 ASSERT(!node->m_next);
1017
1018 return generator.moveToDestinationIfNeeded(dst, generator.emitToNumber(generator.tempDestination(dst), src.get()));
1019}
1020
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +00001021RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
1022{
1023 ArgumentListNode* node = m_args->m_listNode;
1024 RefPtr<RegisterID> src = generator.emitNode(node);
1025 ASSERT(!node->m_next);
1026
1027 return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
1028}
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001029
1030RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isJSArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1031{
1032 ArgumentListNode* node = m_args->m_listNode;
1033 RefPtr<RegisterID> src = generator.emitNode(node);
1034 ASSERT(!node->m_next);
1035
1036 return generator.moveToDestinationIfNeeded(dst, generator.emitIsJSArray(generator.tempDestination(dst), src.get()));
1037}
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +00001038
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001039RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1040{
1041 ArgumentListNode* node = m_args->m_listNode;
1042 RefPtr<RegisterID> src = generator.emitNode(node);
1043 ASSERT(!node->m_next);
1044
1045 return generator.moveToDestinationIfNeeded(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
1046}
1047
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +00001048RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1049{
1050 ArgumentListNode* node = m_args->m_listNode;
1051 RefPtr<RegisterID> src = generator.emitNode(node);
1052 ASSERT(!node->m_next);
1053
1054 return generator.moveToDestinationIfNeeded(dst, generator.emitIsRegExpObject(generator.tempDestination(dst), src.get()));
1055}
1056
utatane.tea@gmail.com0f56f572016-02-08 23:14:47 +00001057RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
1058{
1059 ArgumentListNode* node = m_args->m_listNode;
1060 RefPtr<RegisterID> src = generator.emitNode(node);
1061 ASSERT(!node->m_next);
1062
1063 return generator.moveToDestinationIfNeeded(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
1064}
1065
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001066RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1067{
1068 ArgumentListNode* node = m_args->m_listNode;
1069 RefPtr<RegisterID> src = generator.emitNode(node);
1070 ASSERT(!node->m_next);
1071
1072 return generator.moveToDestinationIfNeeded(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
1073}
1074
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +00001075RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isMap(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1076{
1077 ArgumentListNode* node = m_args->m_listNode;
1078 RefPtr<RegisterID> src = generator.emitNode(node);
1079 ASSERT(!node->m_next);
1080
1081 return generator.moveToDestinationIfNeeded(dst, generator.emitIsMap(generator.tempDestination(dst), src.get()));
1082}
1083
1084RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isSet(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1085{
1086 ArgumentListNode* node = m_args->m_listNode;
1087 RefPtr<RegisterID> src = generator.emitNode(node);
1088 ASSERT(!node->m_next);
1089
1090 return generator.moveToDestinationIfNeeded(dst, generator.emitIsSet(generator.tempDestination(dst), src.get()));
1091}
1092
sbarati@apple.com3cc67a72016-08-18 17:17:41 +00001093RegisterID* BytecodeIntrinsicNode::emit_intrinsic_newArrayWithSize(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1094{
1095 ArgumentListNode* node = m_args->m_listNode;
1096 RefPtr<RegisterID> size = generator.emitNode(node);
1097 ASSERT(!node->m_next);
1098
1099 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst);
1100 generator.emitNewArrayWithSize(finalDestination.get(), size.get());
1101 return finalDestination.get();
1102}
1103
utatane.tea@gmail.combf8978b2016-02-02 19:33:05 +00001104
1105#define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \
1106 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_##name(BytecodeGenerator& generator, RegisterID* dst) \
1107 { \
1108 ASSERT(!m_args); \
1109 ASSERT(type() == Type::Constant); \
1110 if (dst == generator.ignoredResult()) \
1111 return nullptr; \
1112 return generator.emitLoad(dst, generator.vm()->bytecodeIntrinsicRegistry().name##Value(generator)); \
1113 }
1114 JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
1115#undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
1116
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001117// ------------------------------ FunctionCallBracketNode ----------------------------------
1118
1119RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1120{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001121 bool baseIsSuper = m_base->isSuperNode();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001122 bool subscriptIsNonIndexString = isNonIndexStringElement(*m_subscript);
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001123
1124 RefPtr<RegisterID> base;
1125 if (baseIsSuper)
1126 base = emitSuperBaseForCallee(generator);
1127 else {
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001128 if (subscriptIsNonIndexString)
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001129 base = generator.emitNode(m_base);
1130 else
1131 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
1132 }
1133
1134 RefPtr<RegisterID> function;
sbarati@apple.com23315d62016-05-09 20:17:23 +00001135 RefPtr<RegisterID> thisRegister;
1136 if (baseIsSuper) {
1137 // 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.
1138 thisRegister = generator.ensureThis();
1139 }
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001140 if (subscriptIsNonIndexString) {
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001141 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001142 if (baseIsSuper)
1143 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisRegister.get(), static_cast<StringNode*>(m_subscript)->value());
1144 else
1145 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001146 } else {
1147 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
1148 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001149 if (baseIsSuper)
1150 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisRegister.get(), property.get());
1151 else
1152 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001153 }
1154
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001155 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001156 CallArguments callArguments(generator, m_args);
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001157 if (baseIsSuper) {
1158 generator.emitTDZCheck(generator.thisRegister());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001159 generator.emitMove(callArguments.thisRegister(), thisRegister.get());
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001160 } else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001161 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001162 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001163 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001164 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001165}
1166
1167// ------------------------------ FunctionCallDotNode ----------------------------------
1168
1169RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1170{
1171 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001172 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001173 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001174 bool baseIsSuper = m_base->isSuperNode();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001175 if (baseIsSuper)
1176 generator.emitMove(callArguments.thisRegister(), generator.ensureThis());
1177 else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001178 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001179 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001180 if (baseIsSuper) {
1181 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
1182 generator.emitGetById(function.get(), superBase.get(), callArguments.thisRegister(), m_ident);
1183 } else
1184 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001185 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001186 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001187 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001188}
1189
sbarati@apple.com4ddd2ec2017-05-04 12:20:59 +00001190static constexpr size_t maxDistanceToInnermostCallOrApply = 2;
sbarati@apple.com07f9fa92017-04-18 19:02:01 +00001191
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001192RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1193{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001194 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001195 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001196 RefPtr<RegisterID> function;
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001197 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
1198
1199 auto makeFunction = [&] {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001200 if (m_base->isSuperNode()) {
1201 RefPtr<RegisterID> thisValue = generator.ensureThis();
1202 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().callPublicName());
1203 } else
1204 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001205 };
1206
1207 bool emitCallCheck = !generator.isBuiltinFunction();
sbarati@apple.com07f9fa92017-04-18 19:02:01 +00001208 if (m_distanceToInnermostCallOrApply > maxDistanceToInnermostCallOrApply && emitCallCheck) {
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001209 makeFunction();
1210 CallArguments callArguments(generator, m_args);
1211 generator.emitMove(callArguments.thisRegister(), base.get());
1212 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1213 generator.moveToDestinationIfNeeded(dst, returnValue.get());
1214 return returnValue.get();
1215 }
1216
1217 Ref<Label> realCall = generator.newLabel();
1218 Ref<Label> end = generator.newLabel();
1219
1220 if (emitCallCheck) {
1221 makeFunction();
oliver@apple.comba848d12014-02-12 17:14:23 +00001222 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001223 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001224 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001225 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 +00001226 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
1227 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001228 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001229 argumentsRegister = generator.emitNode(subject);
1230 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
1231 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001232 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 +00001233 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001234 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001235 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +00001236
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001237 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1238 CallArguments callArguments(generator, m_args);
1239 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001240 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001241 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001242 } else {
1243 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1244 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +00001245 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001246 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001247 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001248 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001249 if (emitCallCheck) {
1250 generator.emitJump(end.get());
1251 generator.emitLabel(realCall.get());
1252 {
1253 CallArguments callArguments(generator, m_args);
1254 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001255 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001256 }
1257 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001258 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001259 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001260 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001261}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001262
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001263static bool areTrivialApplyArguments(ArgumentsNode* args)
1264{
1265 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
1266 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
1267}
1268
1269RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1270{
1271 // A few simple cases can be trivially handled as ordinary function calls.
1272 // function.apply(), function.apply(arg) -> identical to function.call
1273 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
1274 bool mayBeCall = areTrivialApplyArguments(m_args);
1275
oliver@apple.comba848d12014-02-12 17:14:23 +00001276 RefPtr<RegisterID> function;
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001277 RefPtr<RegisterID> base = generator.emitNode(m_base);
1278 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
1279 auto makeFunction = [&] {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001280 if (m_base->isSuperNode()) {
1281 RefPtr<RegisterID> thisValue = generator.ensureThis();
1282 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().applyPublicName());
1283 } else
1284 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001285 };
1286
1287 bool emitCallCheck = !generator.isBuiltinFunction();
sbarati@apple.com07f9fa92017-04-18 19:02:01 +00001288 if (m_distanceToInnermostCallOrApply > maxDistanceToInnermostCallOrApply && emitCallCheck) {
sbarati@apple.com3e433d82017-04-18 06:43:54 +00001289 makeFunction();
1290 CallArguments callArguments(generator, m_args);
1291 generator.emitMove(callArguments.thisRegister(), base.get());
1292 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
1293 generator.moveToDestinationIfNeeded(dst, returnValue.get());
1294 return returnValue.get();
1295 }
1296
1297 Ref<Label> realCall = generator.newLabel();
1298 Ref<Label> end = generator.newLabel();
1299 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1300 if (emitCallCheck) {
1301 makeFunction();
oliver@apple.comba848d12014-02-12 17:14:23 +00001302 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
1303 }
1304 if (mayBeCall) {
1305 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
1306 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001307 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
1308 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001309 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
1310 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
1311 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1312 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1313
1314 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
1315 {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001316 Ref<Label> haveThis = generator.newLabel();
1317 Ref<Label> end = generator.newLabel();
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001318 RefPtr<RegisterID> compareResult = generator.newTemporary();
1319 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1320 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
1321 generator.emitMove(thisRegister.get(), value);
1322 generator.emitLoad(index.get(), jsNumber(1));
1323 generator.emitJump(end.get());
1324 generator.emitLabel(haveThis.get());
1325 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1326 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
1327 generator.emitMove(argumentsRegister.get(), value);
1328 generator.emitLoad(index.get(), jsNumber(2));
1329 generator.emitLabel(end.get());
1330 };
1331 generator.emitEnumeration(this, spread->expression(), extractor);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001332 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 +00001333 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +00001334 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
1335 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +00001336 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 +00001337 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1338 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +00001339 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001340 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001341 } else {
1342 m_args->m_listNode = m_args->m_listNode->m_next;
1343 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1344 CallArguments callArguments(generator, m_args);
1345 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001346 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001347 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001348 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001349 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +00001350 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001351 CallArguments callArguments(generator, m_args);
1352 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001353 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001354 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001355 } else {
1356 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
oliver@apple.comba848d12014-02-12 17:14:23 +00001357 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1358 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
1359 RefPtr<RegisterID> argsRegister;
1360 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001361 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +00001362
1363 // Function.prototype.apply ignores extra arguments, but we still
1364 // need to evaluate them for side effects.
1365 while ((args = args->m_next))
1366 generator.emitNode(args->m_expr);
1367
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001368 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 +00001369 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001370 if (emitCallCheck) {
1371 generator.emitJump(end.get());
1372 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001373 CallArguments callArguments(generator, m_args);
1374 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001375 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001376 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001377 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001378 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001379 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001380}
1381
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001382// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001383
ggaren@apple.comf3036112013-04-27 23:14:04 +00001384static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001385{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001386 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001387}
1388
1389static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1390{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001391 if (dst == srcDst)
1392 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1393 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1394 emitIncOrDec(generator, srcDst, oper);
1395 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001396}
1397
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001398RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001399{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001400 if (dst == generator.ignoredResult())
1401 return PrefixNode::emitResolve(generator, dst);
1402
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001403 ASSERT(m_expr->isResolveNode());
1404 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1405 const Identifier& ident = resolve->identifier();
1406
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001407 Variable var = generator.variable(ident);
1408 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001409 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001410 RefPtr<RegisterID> localReg = local;
1411 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001412 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001413 localReg = generator.emitMove(generator.tempDestination(dst), local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001414 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001415 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1416 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1417 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001418 }
oliver@apple.com75f804e2013-03-07 00:25:20 +00001419
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001420 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001421 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1422 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001423 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001424 if (var.isReadOnly()) {
1425 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1426 if (threwException)
1427 return value.get();
1428 }
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001429 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001430 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001431 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001432 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1433 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001434
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001435 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001436}
1437
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001438RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001439{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001440 if (dst == generator.ignoredResult())
1441 return PrefixNode::emitBracket(generator, dst);
1442
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001443 ASSERT(m_expr->isBracketAccessorNode());
1444 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1445 ExpressionNode* baseNode = bracketAccessor->base();
1446 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001447
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001448 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001449 RefPtr<RegisterID> property = generator.emitNode(subscript);
1450
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001451 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001452 RefPtr<RegisterID> value;
1453 RefPtr<RegisterID> thisValue;
1454 if (baseNode->isSuperNode()) {
1455 thisValue = generator.ensureThis();
1456 value = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
1457 } else
1458 value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001459 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001460 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001461 if (baseNode->isSuperNode())
1462 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value.get());
1463 else
1464 generator.emitPutByVal(base.get(), property.get(), value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001465 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001466 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001467}
1468
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001469RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001470{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001471 if (dst == generator.ignoredResult())
1472 return PrefixNode::emitDot(generator, dst);
1473
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001474 ASSERT(m_expr->isDotAccessorNode());
1475 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1476 ExpressionNode* baseNode = dotAccessor->base();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001477 bool baseIsSuper = baseNode->isSuperNode();
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001478 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001479
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001480 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1481
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001482 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001483 RefPtr<RegisterID> value;
1484 RefPtr<RegisterID> thisValue;
1485 if (baseIsSuper) {
1486 thisValue = generator.ensureThis();
1487 value = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), ident);
1488 } else
1489 value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001490 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001491 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001492 if (baseIsSuper)
1493 generator.emitPutById(base.get(), thisValue.get(), ident, value.get());
1494 else
1495 generator.emitPutById(base.get(), ident, value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001496 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001497 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001498}
1499
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001500RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001501{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001502 if (m_expr->isResolveNode())
1503 return emitResolve(generator, dst);
1504
1505 if (m_expr->isBracketAccessorNode())
1506 return emitBracket(generator, dst);
1507
1508 if (m_expr->isDotAccessorNode())
1509 return emitDot(generator, dst);
1510
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001511 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001512 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1513 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001514}
1515
1516// ------------------------------ DeleteResolveNode -----------------------------------
1517
1518RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1519{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001520 Variable var = generator.variable(m_ident);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001521 if (var.local()) {
1522 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001523 return generator.emitLoad(generator.finalDestination(dst), false);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001524 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001525
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001526 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001527 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001528 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
oliver@apple.com58c86752013-07-25 04:02:40 +00001529 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001530}
1531
1532// ------------------------------ DeleteBracketNode -----------------------------------
1533
1534RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1535{
1536 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001537 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001538
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001539 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001540 if (m_base->isSuperNode())
1541 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001542 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001543}
1544
1545// ------------------------------ DeleteDotNode -----------------------------------
1546
1547RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1548{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001549 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001550
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001551 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001552 if (m_base->isSuperNode())
1553 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001554 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001555}
1556
1557// ------------------------------ DeleteValueNode -----------------------------------
1558
1559RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1560{
1561 generator.emitNode(generator.ignoredResult(), m_expr);
1562
1563 // delete on a non-location expression ignores the value and returns true
1564 return generator.emitLoad(generator.finalDestination(dst), true);
1565}
1566
1567// ------------------------------ VoidNode -------------------------------------
1568
1569RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1570{
1571 if (dst == generator.ignoredResult()) {
1572 generator.emitNode(generator.ignoredResult(), m_expr);
1573 return 0;
1574 }
1575 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1576 return generator.emitLoad(dst, jsUndefined());
1577}
1578
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001579// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001580
1581RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1582{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001583 Variable var = generator.variable(m_ident);
1584 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001585 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001586 if (dst == generator.ignoredResult())
1587 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001588 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001589 }
1590
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001591 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1592 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001593 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001594 if (dst == generator.ignoredResult())
1595 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001596 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001597}
1598
1599// ------------------------------ TypeOfValueNode -----------------------------------
1600
1601RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1602{
1603 if (dst == generator.ignoredResult()) {
1604 generator.emitNode(generator.ignoredResult(), m_expr);
1605 return 0;
1606 }
1607 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1608 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1609}
1610
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001611// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001612
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001613RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001614{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001615 ASSERT(m_expr->isResolveNode());
1616 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1617 const Identifier& ident = resolve->identifier();
1618
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001619 Variable var = generator.variable(ident);
1620 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001621 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001622 RefPtr<RegisterID> localReg = local;
1623 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001624 generator.emitReadOnlyExceptionIfNeeded(var);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001625 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001626 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001627 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001628 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001629 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001630 generator.emitMove(localReg.get(), tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001631 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001632 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1633 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001634 emitIncOrDec(generator, localReg.get(), m_operator);
1635 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001636 }
1637
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001638 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001639 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1640 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001641 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001642 if (var.isReadOnly()) {
1643 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1644 if (threwException)
1645 return value.get();
1646 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001647
oliver@apple.com58c86752013-07-25 04:02:40 +00001648 emitIncOrDec(generator, value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001649 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001650 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001651 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1652 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001653 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001654}
1655
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001656RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001657{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001658 ASSERT(m_expr->isBracketAccessorNode());
1659 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1660 ExpressionNode* baseNode = bracketAccessor->base();
1661 ExpressionNode* subscript = bracketAccessor->subscript();
1662
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001663 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001664 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001665 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1666
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001667 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001668 RegisterID* value;
1669 RefPtr<RegisterID> thisValue;
1670 if (baseNode->isSuperNode()) {
1671 thisValue = generator.ensureThis();
1672 value = generator.emitGetByVal(propDst.get(), base.get(), thisValue.get(), property.get());
1673 } else
1674 value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001675 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001676 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001677 if (baseNode->isSuperNode())
1678 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
1679 else
1680 generator.emitPutByVal(base.get(), property.get(), value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001681 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001682 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1683}
1684
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001685RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001686{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001687 ASSERT(m_expr->isDotAccessorNode());
1688 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1689 ExpressionNode* baseNode = dotAccessor->base();
1690 const Identifier& ident = dotAccessor->identifier();
1691
1692 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001693 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1694
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001695 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001696 RegisterID* value;
1697 RefPtr<RegisterID> thisValue;
1698 if (baseNode->isSuperNode()) {
1699 thisValue = generator.ensureThis();
1700 value = generator.emitGetById(propDst.get(), base.get(), thisValue.get(), ident);
1701 } else
1702 value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001703 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001704 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001705 if (baseNode->isSuperNode())
1706 generator.emitPutById(base.get(), thisValue.get(), ident, value);
1707 else
1708 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001709 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001710 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1711}
1712
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001713RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001714{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001715 if (m_expr->isResolveNode())
1716 return emitResolve(generator, dst);
1717
1718 if (m_expr->isBracketAccessorNode())
1719 return emitBracket(generator, dst);
1720
1721 if (m_expr->isDotAccessorNode())
1722 return emitDot(generator, dst);
1723
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001724 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001725 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1726 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001727}
1728
1729// ------------------------------ Unary Operation Nodes -----------------------------------
1730
1731RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1732{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001733 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001734 generator.emitExpressionInfo(position(), position(), position());
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00001735 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001736}
1737
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001738// ------------------------------ UnaryPlusNode -----------------------------------
1739
1740RegisterID* UnaryPlusNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1741{
1742 ASSERT(opcodeID() == op_to_number);
1743 RefPtr<RegisterID> src = generator.emitNode(expr());
1744 generator.emitExpressionInfo(position(), position(), position());
1745 return generator.emitToNumber(generator.finalDestination(dst), src.get());
1746}
1747
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001748// ------------------------------ BitwiseNotNode -----------------------------------
1749
1750RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1751{
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00001752 RefPtr<RegisterID> src2 = generator.emitLoad(nullptr, jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001753 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1754 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 +00001755}
1756
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001757// ------------------------------ LogicalNotNode -----------------------------------
1758
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001759void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001760{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00001761 if (UNLIKELY(needsDebugHook()))
1762 generator.emitDebugHook(this);
1763
1764 // Reverse the true and false targets.
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001765 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001766}
1767
1768
1769// ------------------------------ Binary Operation Nodes -----------------------------------
1770
1771// BinaryOpNode::emitStrcat:
1772//
1773// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1774// more values, where we can determine a set of separate op_add operations would be operating on
1775// string values.
1776//
1777// This function expects to be operating on a graph of AST nodes looking something like this:
1778//
1779// (a)... (b)
1780// \ /
1781// (+) (c)
1782// \ /
1783// [d] ((+))
1784// \ /
1785// [+=]
1786//
1787// The assignment operation is optional, if it exists the register holding the value on the
1788// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1789//
1790// The method should be called on the node at the root of the tree of regular binary add
1791// operations (marked in the diagram with a double set of parentheses). This node must
1792// be performing a string concatenation (determined by statically detecting that at least
1793// one child must be a string).
1794//
1795// Since the minimum number of values being concatenated together is expected to be 3, if
1796// a lhs to a concatenating assignment is not provided then the root add should have at
1797// least one left child that is also an add that can be determined to be operating on strings.
1798//
1799RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1800{
1801 ASSERT(isAdd());
1802 ASSERT(resultDescriptor().definitelyIsString());
1803
1804 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1805 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1806 // added first, and the leftmost child is never added, so the vector produced for the
1807 // example above will be [ c, b ].
1808 Vector<ExpressionNode*, 16> reverseExpressionList;
1809 reverseExpressionList.append(m_expr2);
1810
1811 // Examine the left child of the add. So long as this is a string add, add its right-child
1812 // to the list, and keep processing along the left fork.
1813 ExpressionNode* leftMostAddChild = m_expr1;
1814 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1815 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1816 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1817 }
1818
1819 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1820
1821 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1822 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1823 // op_strcat node handle its conversion if required).
1824 if (lhs)
1825 temporaryRegisters.append(generator.newTemporary());
1826
1827 // Emit code for the leftmost node ((a) in the example).
1828 temporaryRegisters.append(generator.newTemporary());
1829 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1830 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1831
1832 // Note on ordering of conversions:
1833 //
1834 // We maintain the same ordering of conversions as we would see if the concatenations
1835 // was performed as a sequence of adds (otherwise this optimization could change
1836 // behaviour should an object have been provided a valueOf or toString method).
1837 //
1838 // Considering the above example, the sequnce of execution is:
1839 // * evaluate operand (a)
1840 // * evaluate operand (b)
1841 // * convert (a) to primitive <- (this would be triggered by the first add)
1842 // * convert (b) to primitive <- (ditto)
1843 // * evaluate operand (c)
1844 // * convert (c) to primitive <- (this would be triggered by the second add)
1845 // And optionally, if there is an assignment:
1846 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1847 //
1848 // As such we do not plant an op to convert the leftmost child now. Instead, use
1849 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1850 // once the second node has been generated. However, if the leftmost child is an
1851 // immediate we can trivially determine that no conversion will be required.
1852 // If this is the case
1853 if (leftMostAddChild->isString())
1854 leftMostAddChildTempRegister = 0;
1855
1856 while (reverseExpressionList.size()) {
1857 ExpressionNode* node = reverseExpressionList.last();
1858 reverseExpressionList.removeLast();
1859
1860 // Emit the code for the current node.
1861 temporaryRegisters.append(generator.newTemporary());
1862 generator.emitNode(temporaryRegisters.last().get(), node);
1863
1864 // On the first iteration of this loop, when we first reach this point we have just
1865 // generated the second node, which means it is time to convert the leftmost operand.
1866 if (leftMostAddChildTempRegister) {
1867 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1868 leftMostAddChildTempRegister = 0; // Only do this once.
1869 }
1870 // Plant a conversion for this node, if necessary.
1871 if (!node->isString())
1872 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1873 }
1874 ASSERT(temporaryRegisters.size() >= 3);
1875
1876 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1877 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1878 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001879 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001880 // If there is an assignment convert the lhs now. This will also copy lhs to
1881 // the temporary register we allocated for it.
1882 if (lhs)
1883 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1884
1885 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1886}
1887
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001888void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001889{
1890 TriState branchCondition;
1891 ExpressionNode* branchExpression;
1892 tryFoldToBranch(generator, branchCondition, branchExpression);
1893
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00001894 if (UNLIKELY(needsDebugHook())) {
1895 if (branchCondition != MixedTriState)
1896 generator.emitDebugHook(this);
1897 }
1898
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001899 if (branchCondition == MixedTriState)
1900 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1901 else if (branchCondition == TrueTriState)
1902 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1903 else
1904 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1905}
1906
1907static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1908{
1909 ResultType expressionType = branchExpression->resultDescriptor();
1910
1911 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1912 return true;
1913 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1914 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1915 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1916 return true;
1917
1918 return false;
1919}
1920
1921void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1922{
1923 branchCondition = MixedTriState;
1924 branchExpression = 0;
1925
1926 ConstantNode* constant = 0;
1927 if (m_expr1->isConstant()) {
1928 constant = static_cast<ConstantNode*>(m_expr1);
1929 branchExpression = m_expr2;
1930 } else if (m_expr2->isConstant()) {
1931 constant = static_cast<ConstantNode*>(m_expr2);
1932 branchExpression = m_expr1;
1933 }
1934
1935 if (!constant)
1936 return;
1937 ASSERT(branchExpression);
1938
1939 OpcodeID opcodeID = this->opcodeID();
1940 JSValue value = constant->jsValue(generator);
1941 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1942 if (!canFoldToBranch)
1943 return;
1944
1945 if (opcodeID == op_eq || opcodeID == op_stricteq)
1946 branchCondition = triState(value.pureToBoolean());
1947 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1948 branchCondition = triState(!value.pureToBoolean());
1949}
1950
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001951RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1952{
1953 OpcodeID opcodeID = this->opcodeID();
1954
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001955 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001956 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001957 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001958 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001959
1960 if (opcodeID == op_neq) {
1961 if (m_expr1->isNull() || m_expr2->isNull()) {
1962 RefPtr<RegisterID> src = generator.tempDestination(dst);
1963 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1964 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1965 }
1966 }
1967
oliver@apple.comece74042012-12-01 00:50:39 +00001968 ExpressionNode* left = m_expr1;
1969 ExpressionNode* right = m_expr2;
1970 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1971 if (left->isString())
1972 std::swap(left, right);
1973 }
1974
1975 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001976 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001977 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001978 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001979 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001980 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1981 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001982 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001983 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001984 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001985 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001986 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001987 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1988 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001989 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 +00001990 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1991 return generator.emitUnaryOp(op_unsigned, result, result);
1992 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001993}
1994
1995RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1996{
1997 if (m_expr1->isNull() || m_expr2->isNull()) {
1998 RefPtr<RegisterID> src = generator.tempDestination(dst);
1999 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
2000 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
2001 }
2002
oliver@apple.comece74042012-12-01 00:50:39 +00002003 ExpressionNode* left = m_expr1;
2004 ExpressionNode* right = m_expr2;
2005 if (left->isString())
2006 std::swap(left, right);
2007
2008 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002009 RefPtr<RegisterID> src2 = generator.emitNode(right);
2010 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002011}
2012
2013RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2014{
oliver@apple.comece74042012-12-01 00:50:39 +00002015 ExpressionNode* left = m_expr1;
2016 ExpressionNode* right = m_expr2;
2017 if (left->isString())
2018 std::swap(left, right);
2019
2020 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002021 RefPtr<RegisterID> src2 = generator.emitNode(right);
2022 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002023}
2024
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002025RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2026{
2027 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002028 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002029 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002030 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 +00002031}
2032
2033RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2034{
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002035 RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
2036 RefPtr<RegisterID> isObject = generator.newTemporary();
2037 RefPtr<RegisterID> isCustom = generator.newTemporary();
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00002038 RefPtr<RegisterID> prototype = generator.newTemporary();
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002039 RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2040 RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
2041 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002042 Ref<Label> custom = generator.newLabel();
2043 Ref<Label> done = generator.newLabel();
2044 Ref<Label> typeError = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002045
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002046 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002047 generator.emitIsObject(isObject.get(), constructor.get());
2048 generator.emitJumpIfFalse(isObject.get(), typeError.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00002049
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002050 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002051 generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002052
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002053 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002054 generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
2055
2056 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2057 generator.emitJumpIfTrue(isCustom.get(), custom.get());
2058
2059 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2060 generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
2061
2062 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2063 generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
2064
2065 generator.emitJump(done.get());
2066
2067 generator.emitLabel(typeError.get());
2068 generator.emitThrowTypeError("Right hand side of instanceof is not an object");
2069
2070 generator.emitLabel(custom.get());
2071
2072 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2073 generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
2074
2075 generator.emitLabel(done.get());
2076
2077 return dstReg.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002078}
2079
keith_miller@apple.com6fc2fb72017-02-09 00:02:20 +00002080// ------------------------------ InNode ----------------------------
2081
2082RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2083{
2084 RefPtr<RegisterID> key = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2085 RefPtr<RegisterID> base = generator.emitNode(m_expr2);
2086 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2087 return generator.emitIn(generator.finalDestination(dst, key.get()), key.get(), base.get());
2088}
2089
2090
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002091// ------------------------------ LogicalOpNode ----------------------------
2092
2093RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2094{
2095 RefPtr<RegisterID> temp = generator.tempDestination(dst);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002096 Ref<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002097
2098 generator.emitNode(temp.get(), m_expr1);
2099 if (m_operator == OpLogicalAnd)
2100 generator.emitJumpIfFalse(temp.get(), target.get());
2101 else
2102 generator.emitJumpIfTrue(temp.get(), target.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002103 generator.emitNodeInTailPosition(temp.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002104 generator.emitLabel(target.get());
2105
2106 return generator.moveToDestinationIfNeeded(dst, temp.get());
2107}
2108
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002109void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002110{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002111 if (UNLIKELY(needsDebugHook()))
2112 generator.emitDebugHook(this);
2113
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002114 Ref<Label> afterExpr1 = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002115 if (m_operator == OpLogicalAnd)
2116 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
2117 else
2118 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
2119 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002120
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002121 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002122}
2123
2124// ------------------------------ ConditionalNode ------------------------------
2125
2126RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2127{
2128 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002129 Ref<Label> beforeElse = generator.newLabel();
2130 Ref<Label> afterElse = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002131
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002132 Ref<Label> beforeThen = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002133 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
2134 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002135
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002136 generator.emitProfileControlFlow(m_expr1->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002137 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002138 generator.emitJump(afterElse.get());
2139
2140 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002141 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002142 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002143
2144 generator.emitLabel(afterElse.get());
2145
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002146 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002147
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002148 return newDst.get();
2149}
2150
2151// ------------------------------ ReadModifyResolveNode -----------------------------------
2152
2153// FIXME: should this be moved to be a method on BytecodeGenerator?
2154static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
2155{
2156 OpcodeID opcodeID;
2157 switch (oper) {
2158 case OpMultEq:
2159 opcodeID = op_mul;
2160 break;
2161 case OpDivEq:
2162 opcodeID = op_div;
2163 break;
2164 case OpPlusEq:
2165 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
2166 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
2167 opcodeID = op_add;
2168 break;
2169 case OpMinusEq:
2170 opcodeID = op_sub;
2171 break;
2172 case OpLShift:
2173 opcodeID = op_lshift;
2174 break;
2175 case OpRShift:
2176 opcodeID = op_rshift;
2177 break;
2178 case OpURShift:
2179 opcodeID = op_urshift;
2180 break;
2181 case OpAndEq:
2182 opcodeID = op_bitand;
2183 break;
2184 case OpXOrEq:
2185 opcodeID = op_bitxor;
2186 break;
2187 case OpOrEq:
2188 opcodeID = op_bitor;
2189 break;
2190 case OpModEq:
2191 opcodeID = op_mod;
2192 break;
utatane.tea@gmail.come9906382016-07-21 07:33:28 +00002193 case OpPowEq:
2194 opcodeID = op_pow;
2195 break;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002196 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00002197 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002198 return dst;
2199 }
2200
2201 RegisterID* src2 = generator.emitNode(m_right);
2202
2203 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2204 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2205 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002206 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00002207 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
2208 if (oper == OpURShift)
2209 return generator.emitUnaryOp(op_unsigned, result, result);
2210 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002211}
2212
2213RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2214{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002215 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002216 Variable var = generator.variable(m_ident);
2217 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002218 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002219 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002220 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002221 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2222 generator.emitProfileType(result, divotStart(), divotEnd());
2223 return result;
ggaren@apple.com6e309822012-09-05 21:44:43 +00002224 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002225
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002226 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002227 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002228 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002229 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002230 generator.emitMove(local, result.get());
2231 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002232 generator.emitProfileType(local, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002233 return generator.moveToDestinationIfNeeded(dst, result.get());
2234 }
2235
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002236 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2237 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002238 generator.emitProfileType(result, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002239 return generator.moveToDestinationIfNeeded(dst, result);
2240 }
2241
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002242 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002243 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2244 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002245 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002246 if (var.isReadOnly()) {
2247 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2248 if (threwException)
2249 return value.get();
2250 }
oliver@apple.com58c86752013-07-25 04:02:40 +00002251 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 +00002252 RegisterID* returnResult = result.get();
2253 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002254 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002255 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2256 }
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002257 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002258}
2259
sbarati@apple.come67fd782016-04-19 01:38:30 +00002260static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
2261{
2262 switch (assignmentContext) {
2263 case AssignmentContext::DeclarationStatement:
2264 return InitializationMode::Initialization;
2265 case AssignmentContext::ConstDeclarationStatement:
2266 return InitializationMode::ConstInitialization;
2267 case AssignmentContext::AssignmentExpression:
2268 return InitializationMode::NotInitialization;
2269 }
2270
2271 ASSERT_NOT_REACHED();
2272 return InitializationMode::NotInitialization;
2273}
2274
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002275// ------------------------------ AssignResolveNode -----------------------------------
2276
2277RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2278{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002279 Variable var = generator.variable(m_ident);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002280 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002281 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002282 RegisterID* result = nullptr;
2283 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2284 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002285
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002286 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002287 result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002288 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002289 generator.emitProfileType(result, var, divotStart(), divotEnd());
2290 } else if (var.isSpecial()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002291 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
2292 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002293 generator.emitMove(local, tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002294 generator.emitProfileType(local, var, divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002295 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002296 result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
2297 } else {
2298 RegisterID* right = generator.emitNode(local, m_right);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002299 generator.emitProfileType(right, var, divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002300 generator.invalidateForInContextForLocal(local);
2301 result = generator.moveToDestinationIfNeeded(dst, right);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002302 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002303
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002304 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002305 generator.liftTDZCheckIfPossible(var);
2306 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002307 }
2308
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002309 if (generator.isStrictMode())
2310 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002311 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002312 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2313 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002314 if (dst == generator.ignoredResult())
2315 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00002316 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002317 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002318 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002319 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2320 if (threwException)
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002321 return result;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002322 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002323 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002324 RegisterID* returnResult = result.get();
2325 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002326 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002327 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2328 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002329
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002330 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002331 generator.liftTDZCheckIfPossible(var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002332 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002333}
2334
2335// ------------------------------ AssignDotNode -----------------------------------
2336
2337RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2338{
2339 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2340 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002341 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002342 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002343 RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
2344 if (m_base->isSuperNode()) {
2345 RefPtr<RegisterID> thisValue = generator.ensureThis();
2346 generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
2347 } else
2348 generator.emitPutById(base.get(), m_ident, forwardResult.get());
2349 generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
2350 return generator.moveToDestinationIfNeeded(dst, forwardResult.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002351}
2352
2353// ------------------------------ ReadModifyDotNode -----------------------------------
2354
2355RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2356{
2357 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2358
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002359 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002360 RefPtr<RegisterID> value;
2361 RefPtr<RegisterID> thisValue;
2362 if (m_base->isSuperNode()) {
2363 thisValue = generator.ensureThis();
2364 value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
2365 } else
2366 value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002367 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 +00002368
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002369 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002370 RegisterID* ret;
2371 if (m_base->isSuperNode())
2372 ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
2373 else
2374 ret = generator.emitPutById(base.get(), m_ident, updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002375 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002376 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002377}
2378
2379// ------------------------------ AssignErrorNode -----------------------------------
2380
2381RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2382{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002383 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002384}
2385
2386// ------------------------------ AssignBracketNode -----------------------------------
2387
2388RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2389{
2390 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2391 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2392 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002393 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002394
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002395 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002396 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00002397
sbarati@apple.com23315d62016-05-09 20:17:23 +00002398 if (isNonIndexStringElement(*m_subscript)) {
2399 if (m_base->isSuperNode()) {
2400 RefPtr<RegisterID> thisValue = generator.ensureThis();
2401 generator.emitPutById(base.get(), thisValue.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2402 } else
2403 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2404 } else {
2405 if (m_base->isSuperNode()) {
2406 RefPtr<RegisterID> thisValue = generator.ensureThis();
2407 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), forwardResult);
2408 } else
2409 generator.emitPutByVal(base.get(), property.get(), forwardResult);
2410 }
akling@apple.come09d0422014-11-13 19:18:43 +00002411
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002412 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00002413 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002414}
2415
2416// ------------------------------ ReadModifyBracketNode -----------------------------------
2417
2418RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2419{
2420 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2421 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2422
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002423 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002424 RefPtr<RegisterID> value;
2425 RefPtr<RegisterID> thisValue;
2426 if (m_base->isSuperNode()) {
2427 thisValue = generator.ensureThis();
2428 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisValue.get(), property.get());
2429 } else
2430 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002431 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 +00002432
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002433 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002434 if (m_base->isSuperNode())
2435 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), updatedValue);
2436 else
2437 generator.emitPutByVal(base.get(), property.get(), updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002438 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002439
2440 return updatedValue;
2441}
2442
2443// ------------------------------ CommaNode ------------------------------------
2444
2445RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2446{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002447 CommaNode* node = this;
2448 for (; node && node->next(); node = node->next())
2449 generator.emitNode(generator.ignoredResult(), node->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002450 return generator.emitNodeInTailPosition(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002451}
2452
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002453// ------------------------------ SourceElements -------------------------------
2454
2455
2456inline StatementNode* SourceElements::lastStatement() const
2457{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002458 return m_tail;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002459}
2460
2461inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2462{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002463 for (StatementNode* statement = m_head; statement; statement = statement->next())
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002464 generator.emitNodeInTailPosition(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002465}
2466
2467// ------------------------------ BlockNode ------------------------------------
2468
2469inline StatementNode* BlockNode::lastStatement() const
2470{
2471 return m_statements ? m_statements->lastStatement() : 0;
2472}
2473
ggaren@apple.comddc6f102015-03-20 20:12:10 +00002474StatementNode* BlockNode::singleStatement() const
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002475{
2476 return m_statements ? m_statements->singleStatement() : 0;
2477}
2478
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002479void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002480{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002481 if (!m_statements)
2482 return;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002483 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002484 m_statements->emitBytecode(generator, dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002485 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002486}
2487
2488// ------------------------------ EmptyStatementNode ---------------------------
2489
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002490void EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002491{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002492 RELEASE_ASSERT(needsDebugHook());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002493}
2494
2495// ------------------------------ DebuggerStatementNode ---------------------------
2496
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002497void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002498{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002499 generator.emitDebugHook(DidReachBreakpoint, position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002500}
2501
2502// ------------------------------ ExprStatementNode ----------------------------
2503
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002504void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002505{
2506 ASSERT(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002507 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002508}
2509
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002510// ------------------------------ DeclarationStatement ----------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002511
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002512void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002513{
2514 ASSERT(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002515 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002516}
2517
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002518// ------------------------------ EmptyVarExpression ----------------------------
2519
2520RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2521{
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002522 // 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 +00002523 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002524 return nullptr;
2525
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002526 Variable var = generator.variable(m_ident);
2527 if (RegisterID* local = var.local())
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002528 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002529 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002530 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2531 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002532 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002533 }
2534
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002535 return nullptr;
2536}
2537
2538// ------------------------------ EmptyLetExpression ----------------------------
2539
2540RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2541{
2542 // Lexical declarations like 'let' must move undefined into their variables so we don't
2543 // get TDZ errors for situations like this: `let x; x;`
2544 Variable var = generator.variable(m_ident);
2545 if (RegisterID* local = var.local()) {
2546 generator.emitLoad(local, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002547 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002548 } else {
2549 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2550 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002551 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002552 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002553 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002554
sbarati@apple.coma5cf2f12016-03-29 22:11:24 +00002555 generator.liftTDZCheckIfPossible(var);
2556
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002557 // 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 +00002558 return nullptr;
2559}
2560
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002561// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002562
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002563static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002564{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002565 if (statementNode->isBlock())
2566 return static_cast<BlockNode*>(statementNode)->singleStatement();
2567 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002568}
2569
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002570bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2571 Label*& trueTarget, FallThroughMode& fallThroughMode)
2572{
2573 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2574 if (!singleStatement)
2575 return false;
2576
2577 if (singleStatement->isBreak()) {
2578 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2579 Label* target = breakNode->trivialTarget(generator);
2580 if (!target)
2581 return false;
2582 trueTarget = target;
2583 fallThroughMode = FallThroughMeansFalse;
2584 return true;
2585 }
2586
2587 if (singleStatement->isContinue()) {
2588 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2589 Label* target = continueNode->trivialTarget(generator);
2590 if (!target)
2591 return false;
2592 trueTarget = target;
2593 fallThroughMode = FallThroughMeansFalse;
2594 return true;
2595 }
2596
2597 return false;
2598}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002599
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002600void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002601{
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002602 Ref<Label> beforeThen = generator.newLabel();
2603 Ref<Label> beforeElse = generator.newLabel();
2604 Ref<Label> afterElse = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002605
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002606 Label* trueTarget = beforeThen.ptr();
2607 Label& falseTarget = beforeElse.get();
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002608 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2609 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2610
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002611 generator.emitNodeInConditionContext(m_condition, *trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002612 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002613 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002614
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002615 if (!didFoldIfBlock) {
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002616 generator.emitNodeInTailPosition(dst, m_ifBlock);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002617 if (m_elseBlock)
2618 generator.emitJump(afterElse.get());
2619 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002620
2621 generator.emitLabel(beforeElse.get());
2622
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002623 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002624 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002625 generator.emitNodeInTailPosition(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002626 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002627
2628 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002629 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2630 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002631}
2632
2633// ------------------------------ DoWhileNode ----------------------------------
2634
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002635void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002636{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002637 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002638
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002639 Ref<Label> topOfLoop = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002640 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002641 generator.emitLoopHint();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002642
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002643 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002644
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002645 generator.emitLabel(*scope->continueTarget());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002646 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002647
2648 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002649}
2650
2651// ------------------------------ WhileNode ------------------------------------
2652
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002653void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002654{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002655 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002656 Ref<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002657
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002658 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002659
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002660 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002661 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002662
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002663 generator.emitProfileControlFlow(m_statement->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002664 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002665
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002666 generator.emitLabel(*scope->continueTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002667
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002668 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002669
2670 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002671
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002672 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002673}
2674
2675// ------------------------------ ForNode --------------------------------------
2676
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002677void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002678{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002679 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002680
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002681 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002682 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002683
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002684 if (m_expr1)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002685 generator.emitNode(generator.ignoredResult(), m_expr1);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002686
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002687 Ref<Label> topOfLoop = generator.newLabel();
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002688 if (m_expr2)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002689 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002690
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002691 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002692 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002693 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002694
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002695 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002696
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002697 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002698 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002699 if (m_expr3)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002700 generator.emitNode(generator.ignoredResult(), m_expr3);
2701
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(), FallThroughMeansFalse);
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002704 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002705 generator.emitJump(topOfLoop.get());
2706
2707 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002708 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002709 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002710}
2711
2712// ------------------------------ ForInNode ------------------------------------
2713
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002714RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002715{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002716 if (m_lexpr->isResolveNode()) {
2717 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002718 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002719 }
2720
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002721 if (m_lexpr->isDestructuringNode()) {
2722 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002723 auto binding = assignNode->bindings();
2724 if (!binding->isBindingNode())
2725 return nullptr;
2726
2727 auto simpleBinding = static_cast<BindingNode*>(binding);
2728 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002729 Variable var = generator.variable(ident);
2730 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002731 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002732 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002733 }
2734
2735 return nullptr;
2736}
2737
2738void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2739{
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002740 auto lambdaEmitResolveVariable = [&](const Identifier& ident)
2741 {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002742 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002743 if (RegisterID* local = var.local()) {
2744 if (var.isReadOnly())
2745 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002746 generator.emitMove(local, propertyName);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002747 } else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002748 if (generator.isStrictMode())
2749 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002750 if (var.isReadOnly())
2751 generator.emitReadOnlyExceptionIfNeeded(var);
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00002752 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002753 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00002754 generator.emitPutToScope(scope.get(), var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002755 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002756 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002757 };
2758
2759 if (m_lexpr->isResolveNode()) {
2760 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2761 lambdaEmitResolveVariable(ident);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002762 return;
2763 }
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002764
2765 if (m_lexpr->isAssignResolveNode()) {
2766 const Identifier& ident = static_cast<AssignResolveNode*>(m_lexpr)->identifier();
2767 lambdaEmitResolveVariable(ident);
2768 return;
2769 }
2770
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002771 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002772 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2773 const Identifier& ident = assignNode->identifier();
sbarati@apple.com23315d62016-05-09 20:17:23 +00002774 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002775 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002776 if (assignNode->base()->isSuperNode()) {
2777 RefPtr<RegisterID> thisValue = generator.ensureThis();
2778 generator.emitPutById(base.get(), thisValue.get(), ident, propertyName);
2779 } else
2780 generator.emitPutById(base.get(), ident, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002781 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002782 return;
2783 }
2784 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002785 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002786 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002787 RefPtr<RegisterID> subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002788 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002789 if (assignNode->base()->isSuperNode()) {
2790 RefPtr<RegisterID> thisValue = generator.ensureThis();
2791 generator.emitPutByVal(base.get(), thisValue.get(), subscript.get(), propertyName);
2792 } else
2793 generator.emitPutByVal(base.get(), subscript.get(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002794 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002795 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002796 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002797
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002798 if (m_lexpr->isDestructuringNode()) {
2799 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002800 auto binding = assignNode->bindings();
2801 if (!binding->isBindingNode()) {
2802 assignNode->bindings()->bindValue(generator, propertyName);
2803 return;
2804 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002805
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002806 auto simpleBinding = static_cast<BindingNode*>(binding);
2807 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002808 Variable var = generator.variable(ident);
2809 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002810 assignNode->bindings()->bindValue(generator, propertyName);
2811 return;
2812 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002813 generator.emitMove(var.local(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002814 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002815 return;
2816 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002817
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002818 RELEASE_ASSERT_NOT_REACHED();
2819}
2820
commit-queue@webkit.org3057eed2016-09-21 22:52:37 +00002821void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002822{
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002823 if (!m_lexpr->isAssignResolveNode() && !m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002824 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002825 return;
2826 }
2827
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002828 Ref<Label> end = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002829
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002830 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002831 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002832
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002833 if (m_lexpr->isAssignResolveNode())
2834 generator.emitNode(generator.ignoredResult(), m_lexpr);
2835
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002836 RefPtr<RegisterID> base = generator.newTemporary();
2837 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002838 RefPtr<RegisterID> enumerator;
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002839
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002840 generator.emitNode(base.get(), m_expr);
2841 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002842 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002843
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002844 // Pause at the assignment expression for each for..in iteration.
2845 generator.emitDebugHook(m_lexpr);
2846
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002847 int profilerStartOffset = m_statement->startOffset();
2848 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002849
2850 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2851
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002852 // Indexed property loop.
2853 {
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002854 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002855 Ref<Label> loopStart = generator.newLabel();
2856 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002857
msaboff@apple.comb644c252015-03-24 10:05:21 +00002858 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002859 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2860 RefPtr<RegisterID> propertyName = generator.newTemporary();
2861
2862 generator.emitLabel(loopStart.get());
2863 generator.emitLoopHint();
2864
2865 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2866 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2867 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002868 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002869
2870 generator.emitToIndexString(propertyName.get(), i.get());
2871 this->emitLoopHeader(generator, propertyName.get());
2872
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002873 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002874
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002875 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002876 generator.emitNode(dst, m_statement);
2877 generator.popIndexedForInScope(local.get());
2878
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002879 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002880
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002881 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002882 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002883 generator.emitInc(i.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002884 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002885 generator.emitJump(loopStart.get());
2886
2887 generator.emitLabel(scope->breakTarget());
2888 generator.emitJump(end.get());
2889 generator.emitLabel(loopEnd.get());
2890 }
2891
2892 // Structure property loop.
2893 {
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002894 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002895 Ref<Label> loopStart = generator.newLabel();
2896 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002897
msaboff@apple.comb644c252015-03-24 10:05:21 +00002898 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002899 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002900 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002901
2902 generator.emitLabel(loopStart.get());
2903 generator.emitLoopHint();
2904
2905 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2906 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002907 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002908 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002909
2910 this->emitLoopHeader(generator, propertyName.get());
2911
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002912 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002913
msaboff@apple.comb644c252015-03-24 10:05:21 +00002914 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002915 generator.emitNode(dst, m_statement);
2916 generator.popStructureForInScope(local.get());
2917
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002918 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002919
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002920 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002921 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002922 generator.emitInc(enumeratorIndex.get());
2923 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002924 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002925 generator.emitJump(loopStart.get());
2926
2927 generator.emitLabel(scope->breakTarget());
2928 generator.emitJump(end.get());
2929 generator.emitLabel(loopEnd.get());
2930 }
2931
2932 // Generic property loop.
2933 {
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00002934 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002935 Ref<Label> loopStart = generator.newLabel();
2936 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002937
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002938 RefPtr<RegisterID> propertyName = generator.newTemporary();
2939
msaboff@apple.comb644c252015-03-24 10:05:21 +00002940 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002941
2942 generator.emitLabel(loopStart.get());
2943 generator.emitLoopHint();
2944
msaboff@apple.comb644c252015-03-24 10:05:21 +00002945 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2946 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2947
2948 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002949 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002950
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002951 this->emitLoopHeader(generator, propertyName.get());
2952
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002953 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002954
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002955 generator.emitNode(dst, m_statement);
2956
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002957 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002958 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002959 generator.emitInc(enumeratorIndex.get());
2960 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002961 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
msaboff@apple.comb644c252015-03-24 10:05:21 +00002962 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002963
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002964 generator.emitLabel(scope->breakTarget());
2965 generator.emitJump(end.get());
2966 generator.emitLabel(loopEnd.get());
2967 }
2968
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002969 generator.emitLabel(end.get());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002970 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002971 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002972}
2973
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002974// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002975void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2976{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002977 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002978 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002979 return;
2980 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002981
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002982 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002983 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002984 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002985 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002986 if (m_lexpr->isResolveNode()) {
2987 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002988 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002989 if (RegisterID* local = var.local()) {
2990 if (var.isReadOnly())
2991 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002992 generator.emitMove(local, value);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002993 } else {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002994 if (generator.isStrictMode())
2995 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002996 if (var.isReadOnly())
2997 generator.emitReadOnlyExceptionIfNeeded(var);
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00002998 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002999 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00003000 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
oliver@apple.com72f8a822013-10-17 01:02:34 +00003001 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003002 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00003003 } else if (m_lexpr->isDotAccessorNode()) {
3004 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
3005 const Identifier& ident = assignNode->identifier();
3006 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3007
3008 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003009 if (assignNode->base()->isSuperNode()) {
3010 RefPtr<RegisterID> thisValue = generator.ensureThis();
3011 generator.emitPutById(base.get(), thisValue.get(), ident, value);
3012 } else
3013 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003014 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00003015 } else if (m_lexpr->isBracketAccessorNode()) {
3016 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
3017 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
3018 RegisterID* subscript = generator.emitNode(assignNode->subscript());
3019
3020 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003021 if (assignNode->base()->isSuperNode()) {
3022 RefPtr<RegisterID> thisValue = generator.ensureThis();
3023 generator.emitPutByVal(base.get(), thisValue.get(), subscript, value);
3024 } else
3025 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003026 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00003027 } else {
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003028 ASSERT(m_lexpr->isDestructuringNode());
3029 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00003030 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00003031 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003032 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00003033 generator.emitNode(dst, m_statement);
3034 };
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003035 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
3036 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003037 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00003038}
3039
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003040// ------------------------------ ContinueNode ---------------------------------
3041
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003042Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
3043{
3044 if (generator.shouldEmitDebugHooks())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003045 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003046
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003047 RefPtr<LabelScope> scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003048 ASSERT(scope);
3049
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00003050 if (generator.labelScopeDepth() != scope->scopeDepth())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003051 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003052
3053 return scope->continueTarget();
3054}
3055
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003056void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003057{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003058 RefPtr<LabelScope> scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003059 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003060
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003061 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), *scope->continueTarget());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003062 if (!hasFinally) {
3063 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3064 generator.restoreScopeRegister(lexicalScopeIndex);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003065 generator.emitJump(*scope->continueTarget());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003066 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003067
3068 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003069}
3070
3071// ------------------------------ BreakNode ------------------------------------
3072
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003073Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
3074{
3075 if (generator.shouldEmitDebugHooks())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003076 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003077
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003078 RefPtr<LabelScope> scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003079 ASSERT(scope);
3080
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00003081 if (generator.labelScopeDepth() != scope->scopeDepth())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003082 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003083
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003084 return &scope->breakTarget();
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003085}
3086
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003087void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003088{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003089 RefPtr<LabelScope> scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003090 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003091
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003092 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget());
3093 if (!hasFinally) {
3094 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3095 generator.restoreScopeRegister(lexicalScopeIndex);
3096 generator.emitJump(scope->breakTarget());
3097 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003098
3099 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003100}
3101
3102// ------------------------------ ReturnNode -----------------------------------
3103
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003104void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003105{
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003106 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003107
3108 if (dst == generator.ignoredResult())
3109 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00003110
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003111 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003112
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003113 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003114
3115 bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());
3116 if (!hasFinally) {
3117 generator.emitWillLeaveCallFrameDebugHook();
3118 generator.emitReturn(returnRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003119 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00003120
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003121 generator.emitProfileControlFlow(endOffset());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003122 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
3123 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
3124 if (generator.vm()->controlFlowProfiler())
3125 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003126}
3127
3128// ------------------------------ WithNode -------------------------------------
3129
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003130void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003131{
ggaren@apple.com170d6f22012-09-02 21:27:23 +00003132 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003133 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003134 generator.emitPushWithScope(scope.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003135 generator.emitNodeInTailPosition(dst, m_statement);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003136 generator.emitPopWithScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003137}
3138
3139// ------------------------------ CaseClauseNode --------------------------------
3140
3141inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3142{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003143 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003144 if (!m_statements)
3145 return;
3146 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003147}
3148
3149// ------------------------------ CaseBlockNode --------------------------------
3150
3151enum SwitchKind {
3152 SwitchUnset = 0,
3153 SwitchNumber = 1,
3154 SwitchString = 2,
3155 SwitchNeither = 3
3156};
3157
3158static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
3159{
3160 for (; list; list = list->getNext()) {
3161 ExpressionNode* clauseExpression = list->getClause()->expr();
3162 literalVector.append(clauseExpression);
3163 if (clauseExpression->isNumber()) {
3164 double value = static_cast<NumberNode*>(clauseExpression)->value();
3165 int32_t intVal = static_cast<int32_t>(value);
3166 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
3167 typeForTable = SwitchNeither;
3168 break;
3169 }
3170 if (intVal < min_num)
3171 min_num = intVal;
3172 if (intVal > max_num)
3173 max_num = intVal;
3174 typeForTable = SwitchNumber;
3175 continue;
3176 }
3177 if (clauseExpression->isString()) {
3178 if (typeForTable & ~SwitchString) {
3179 typeForTable = SwitchNeither;
3180 break;
3181 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00003182 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00003183 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00003184 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003185 if (intVal < min_num)
3186 min_num = intVal;
3187 if (intVal > max_num)
3188 max_num = intVal;
3189 }
3190 typeForTable = SwitchString;
3191 continue;
3192 }
3193 typeForTable = SwitchNeither;
3194 break;
3195 }
3196}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003197
3198static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003199{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003200 size_t length = 0;
3201 for (ClauseListNode* node = list1; node; node = node->getNext())
3202 ++length;
3203 for (ClauseListNode* node = list2; node; node = node->getNext())
3204 ++length;
3205 return length;
3206}
3207
3208SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
3209{
3210 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
3211 return SwitchInfo::SwitchNone;
3212
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003213 SwitchKind typeForTable = SwitchUnset;
3214 bool singleCharacterSwitch = true;
3215
3216 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3217 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3218
3219 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
3220 return SwitchInfo::SwitchNone;
3221
3222 if (typeForTable == SwitchNumber) {
3223 int32_t range = max_num - min_num;
3224 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3225 return SwitchInfo::SwitchImmediate;
3226 return SwitchInfo::SwitchNone;
3227 }
3228
3229 ASSERT(typeForTable == SwitchString);
3230
3231 if (singleCharacterSwitch) {
3232 int32_t range = max_num - min_num;
3233 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3234 return SwitchInfo::SwitchCharacter;
3235 }
3236
3237 return SwitchInfo::SwitchString;
3238}
3239
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003240void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003241{
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003242 Vector<Ref<Label>, 8> labelVector;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003243 Vector<ExpressionNode*, 8> literalVector;
3244 int32_t min_num = std::numeric_limits<int32_t>::max();
3245 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003246 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003247
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003248 Ref<Label> defaultLabel = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003249 if (switchType != SwitchInfo::SwitchNone) {
3250 // Prepare the various labels
3251 for (uint32_t i = 0; i < literalVector.size(); i++)
3252 labelVector.append(generator.newLabel());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003253 generator.beginSwitch(switchExpression, switchType);
3254 } else {
3255 // Setup jumps
3256 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3257 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3258 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3259 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3260 labelVector.append(generator.newLabel());
3261 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3262 }
3263
3264 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3265 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3266 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3267 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3268 labelVector.append(generator.newLabel());
3269 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3270 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003271 generator.emitJump(defaultLabel.get());
3272 }
3273
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003274 size_t i = 0;
3275 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3276 generator.emitLabel(labelVector[i++].get());
3277 list->getClause()->emitBytecode(generator, dst);
3278 }
3279
3280 if (m_defaultClause) {
3281 generator.emitLabel(defaultLabel.get());
3282 m_defaultClause->emitBytecode(generator, dst);
3283 }
3284
3285 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3286 generator.emitLabel(labelVector[i++].get());
3287 list->getClause()->emitBytecode(generator, dst);
3288 }
3289 if (!m_defaultClause)
3290 generator.emitLabel(defaultLabel.get());
3291
3292 ASSERT(i == labelVector.size());
3293 if (switchType != SwitchInfo::SwitchNone) {
3294 ASSERT(labelVector.size() == literalVector.size());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003295 generator.endSwitch(labelVector.size(), labelVector, literalVector.data(), defaultLabel.get(), min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003296 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003297}
3298
3299// ------------------------------ SwitchNode -----------------------------------
3300
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003301void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003302{
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003303 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003304
3305 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003306
sbarati@apple.combdbba812015-12-19 00:19:41 +00003307 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::DoNotOptimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003308 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003309 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003310
3311 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003312 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003313}
3314
3315// ------------------------------ LabelNode ------------------------------------
3316
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003317void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003318{
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003319 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003320
utatane.tea@gmail.com276d22b2017-04-29 16:32:59 +00003321 Ref<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00003322 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003323
3324 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003325}
3326
3327// ------------------------------ ThrowNode ------------------------------------
3328
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003329void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003330{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003331 if (dst == generator.ignoredResult())
3332 dst = 0;
3333 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003334 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003335 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003336
3337 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003338}
3339
3340// ------------------------------ TryNode --------------------------------------
3341
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003342void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003343{
3344 // NOTE: The catch and finally blocks must be labeled explicitly, so the
3345 // optimizer knows they may be jumped to from anywhere.
3346
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003347 ASSERT(m_catchBlock || m_finallyBlock);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003348 BytecodeGenerator::CompletionRecordScope completionRecordScope(generator, m_finallyBlock);
3349
3350 RefPtr<Label> catchLabel;
3351 RefPtr<Label> catchEndLabel;
3352 RefPtr<Label> finallyViaThrowLabel;
3353 RefPtr<Label> finallyLabel;
3354 RefPtr<Label> finallyEndLabel;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003355
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003356 Ref<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003357 generator.emitLabel(tryStartLabel.get());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003358
3359 if (m_finallyBlock) {
3360 finallyViaThrowLabel = generator.newLabel();
3361 finallyLabel = generator.newLabel();
3362 finallyEndLabel = generator.newLabel();
3363
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003364 generator.pushFinallyControlFlowScope(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003365 }
3366 if (m_catchBlock) {
3367 catchLabel = generator.newLabel();
3368 catchEndLabel = generator.newLabel();
3369 }
3370
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003371 Label& tryHandlerLabel = m_catchBlock ? *catchLabel : *finallyViaThrowLabel;
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003372 HandlerType tryHandlerType = m_catchBlock ? HandlerType::Catch : HandlerType::Finally;
3373 TryData* tryData = generator.pushTry(tryStartLabel.get(), tryHandlerLabel, tryHandlerType);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003374
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003375 generator.emitNode(dst, m_tryBlock);
3376
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003377 if (m_finallyBlock)
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003378 generator.emitJump(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003379 else
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003380 generator.emitJump(*catchEndLabel);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003381
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003382 Ref<Label> endTryLabel = generator.newEmittedLabel();
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003383 generator.popTry(tryData, endTryLabel.get());
3384
3385 if (m_catchBlock) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003386 // Uncaught exception path: the catch block.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003387 generator.emitLabel(*catchLabel);
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003388 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003389 RegisterID* unused = generator.newTemporary();
3390 generator.emitCatch(unused, thrownValueRegister.get());
3391 generator.restoreScopeRegister();
3392
3393 TryData* tryData = nullptr;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003394 if (m_finallyBlock) {
3395 // If the catch block throws an exception and we have a finally block, then the finally
3396 // block should "catch" that exception.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003397 tryData = generator.pushTry(*catchLabel, *finallyViaThrowLabel, HandlerType::Finally);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003398 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00003399
utatane.tea@gmail.com08fe3112016-01-22 04:21:36 +00003400 generator.emitPushCatchScope(m_lexicalVariables);
3401 m_catchPattern->bindValue(generator, thrownValueRegister.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003402 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003403 if (m_finallyBlock)
3404 generator.emitNode(dst, m_catchBlock);
3405 else
3406 generator.emitNodeInTailPosition(dst, m_catchBlock);
msaboff@apple.com78461ac2016-06-02 04:07:14 +00003407 generator.emitLoad(thrownValueRegister.get(), jsUndefined());
sbarati@apple.com62be0b02015-09-19 15:36:46 +00003408 generator.emitPopCatchScope(m_lexicalVariables);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003409
3410 if (m_finallyBlock) {
3411 generator.emitSetCompletionType(CompletionType::Normal);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003412 generator.emitJump(*finallyLabel);
3413 generator.popTry(tryData, *finallyViaThrowLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003414 }
3415
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003416 generator.emitLabel(*catchEndLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003417 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003418 }
3419
3420 if (m_finallyBlock) {
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003421 FinallyContext finallyContext = generator.popFinallyControlFlowScope();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003422
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003423 // Entry to the finally block for CompletionType::Throw.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003424 generator.emitLabel(*finallyViaThrowLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003425 RegisterID* unused = generator.newTemporary();
3426 generator.emitCatch(generator.completionValueRegister(), unused);
3427 generator.emitSetCompletionType(CompletionType::Throw);
3428
3429 // Entry to the finally block for CompletionTypes other than Throw.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003430 generator.emitLabel(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003431 generator.restoreScopeRegister();
3432
3433 RefPtr<RegisterID> savedCompletionTypeRegister = generator.newTemporary();
3434 generator.emitMove(savedCompletionTypeRegister.get(), generator.completionTypeRegister());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003435
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003436 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003437 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003438 generator.emitNodeInTailPosition(dst, m_finallyBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003439
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003440 generator.emitFinallyCompletion(finallyContext, savedCompletionTypeRegister.get(), *finallyEndLabel);
3441 generator.emitLabel(*finallyEndLabel);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003442 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003443 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003444}
3445
3446// ------------------------------ ScopeNode -----------------------------
3447
3448inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
3449{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003450 if (!m_statements)
3451 return;
3452 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003453}
3454
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003455static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
3456{
3457 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
3458
3459 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3460 generator.emitLoad(dstRegister.get(), jsUndefined());
3461 generator.emitProfileControlFlow(scopeNode.startStartOffset());
3462 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
3463
3464 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
3465 generator.emitEnd(dstRegister.get());
3466}
3467
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003468// ------------------------------ ProgramNode -----------------------------
3469
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003470void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003471{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003472 emitProgramNodeBytecode(generator, *this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003473}
3474
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003475// ------------------------------ ModuleProgramNode --------------------
3476
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003477void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003478{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003479 emitProgramNodeBytecode(generator, *this);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003480}
3481
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003482// ------------------------------ EvalNode -----------------------------
3483
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003484void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003485{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003486 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003487
3488 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3489 generator.emitLoad(dstRegister.get(), jsUndefined());
3490 emitStatementsBytecode(generator, dstRegister.get());
3491
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003492 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003493 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003494}
3495
ggaren@apple.come7afe402015-08-10 20:24:35 +00003496// ------------------------------ FunctionNode -----------------------------
ggaren@apple.com6f851d72014-12-04 23:47:49 +00003497
3498void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003499{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00003500 if (generator.vm()->typeProfiler()) {
utatane.tea@gmail.com3e031ac2017-03-16 05:12:53 +00003501 // If the parameter list is non simple one, it is handled in bindValue's code.
3502 if (m_parameters->isSimpleParameterList()) {
3503 for (size_t i = 0; i < m_parameters->size(); i++) {
3504 BindingNode* bindingNode = static_cast<BindingNode*>(m_parameters->at(i).first);
3505 RegisterID reg(CallFrame::argumentOffset(i));
3506 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, bindingNode->divotStart(), bindingNode->divotEnd());
3507 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003508 }
3509 }
3510
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003511 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003512 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003513
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003514 switch (generator.parseMode()) {
commit-queue@webkit.org67795122017-04-25 06:52:04 +00003515 case SourceParseMode::GeneratorWrapperFunctionMode:
3516 case SourceParseMode::GeneratorWrapperMethodMode: {
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003517 StatementNode* singleStatement = this->singleStatement();
3518 ASSERT(singleStatement->isExprStatement());
3519 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3520 ExpressionNode* expr = exprStatement->expr();
3521 ASSERT(expr->isFuncExprNode());
3522 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003523
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003524 RefPtr<RegisterID> next = generator.newTemporary();
3525 generator.emitNode(next.get(), funcExpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003526
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003527 if (generator.superBinding() == SuperBinding::Needed) {
3528 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3529 emitPutHomeObject(generator, next.get(), homeObject.get());
3530 }
3531
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003532 generator.emitPutGeneratorFields(next.get());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003533
mark.lam@apple.comfa35e782013-11-19 21:55:16 +00003534 ASSERT(startOffset() >= lineStartOffset());
3535 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003536 generator.emitReturn(generator.generatorRegister());
3537 break;
3538 }
3539
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003540 case SourceParseMode::AsyncFunctionMode:
3541 case SourceParseMode::AsyncMethodMode:
3542 case SourceParseMode::AsyncArrowFunctionMode: {
3543 StatementNode* singleStatement = this->singleStatement();
3544 ASSERT(singleStatement->isExprStatement());
3545 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3546 ExpressionNode* expr = exprStatement->expr();
3547 ASSERT(expr->isFuncExprNode());
3548 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
3549
3550 RefPtr<RegisterID> next = generator.newTemporary();
3551 generator.emitNode(next.get(), funcExpr);
3552
gskachkov@gmail.comc78531a2017-01-10 21:13:33 +00003553 if (generator.superBinding() == SuperBinding::Needed || (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isSuperUsedInInnerArrowFunction())) {
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003554 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3555 emitPutHomeObject(generator, next.get(), homeObject.get());
3556 }
gskachkov@gmail.com48a2a9a2017-01-19 17:10:31 +00003557
3558 if (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isThisUsedInInnerArrowFunction())
3559 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003560
3561 generator.emitPutGeneratorFields(next.get());
3562
3563 ASSERT(startOffset() >= lineStartOffset());
3564 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3565
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003566 // load and call @asyncFunctionResume
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003567 auto var = generator.variable(generator.propertyNames().builtinNames().asyncFunctionResumePrivateName());
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003568 RefPtr<RegisterID> scope = generator.newTemporary();
3569 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003570 RefPtr<RegisterID> asyncFunctionResume = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003571
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003572 CallArguments args(generator, nullptr, 4);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003573 unsigned argumentCount = 0;
3574 generator.emitLoad(args.thisRegister(), jsUndefined());
3575 generator.emitMove(args.argumentRegister(argumentCount++), generator.generatorRegister());
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003576 generator.emitMove(args.argumentRegister(argumentCount++), generator.promiseCapabilityRegister());
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003577 generator.emitLoad(args.argumentRegister(argumentCount++), jsUndefined());
3578 generator.emitLoad(args.argumentRegister(argumentCount++), jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
3579 // JSTextPosition(int _line, int _offset, int _lineStartOffset)
3580 JSTextPosition divot(firstLine(), startOffset(), lineStartOffset());
3581
3582 RefPtr<RegisterID> result = generator.newTemporary();
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003583 generator.emitCallInTailPosition(result.get(), asyncFunctionResume.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003584 generator.emitReturn(result.get());
3585 break;
3586 }
3587
3588 case SourceParseMode::AsyncArrowFunctionBodyMode:
3589 case SourceParseMode::AsyncFunctionBodyMode:
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003590 case SourceParseMode::GeneratorBodyMode: {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003591 Ref<Label> generatorBodyLabel = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003592 {
3593 RefPtr<RegisterID> condition = generator.newTemporary();
3594 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))));
3595 generator.emitJumpIfTrue(condition.get(), generatorBodyLabel.get());
3596
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003597 Ref<Label> throwLabel = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003598 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))));
3599 generator.emitJumpIfTrue(condition.get(), throwLabel.get());
3600
3601 generator.emitReturn(generator.generatorValueRegister());
3602
3603 generator.emitLabel(throwLabel.get());
3604 generator.emitThrow(generator.generatorValueRegister());
3605 }
3606
3607 generator.emitLabel(generatorBodyLabel.get());
3608
3609 emitStatementsBytecode(generator, generator.ignoredResult());
3610
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003611 Ref<Label> done = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003612 generator.emitLabel(done.get());
3613 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003614 break;
3615 }
3616
3617 default: {
3618 emitStatementsBytecode(generator, generator.ignoredResult());
3619
3620 StatementNode* singleStatement = this->singleStatement();
3621 ReturnNode* returnNode = 0;
3622
3623 // Check for a return statement at the end of a function composed of a single block.
3624 if (singleStatement && singleStatement->isBlock()) {
3625 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
3626 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
3627 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
3628 }
3629
3630 // If there is no return we must automatically insert one.
3631 if (!returnNode) {
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003632 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isSuperCallUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +00003633 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
3634
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003635 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
3636 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
3637 ASSERT(startOffset() >= lineStartOffset());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003638 generator.emitWillLeaveCallFrameDebugHook();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003639 generator.emitReturn(r0);
3640 return;
3641 }
3642 break;
3643 }
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003644 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003645}
3646
3647// ------------------------------ FuncDeclNode ---------------------------------
3648
sbarati@apple.come86176c2016-04-07 21:01:42 +00003649void FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003650{
sbarati@apple.come86176c2016-04-07 21:01:42 +00003651 generator.hoistSloppyModeFunctionIfNecessary(metadata()->ident());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003652}
3653
3654// ------------------------------ FuncExprNode ---------------------------------
3655
3656RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3657{
3658 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3659}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003660
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00003661// ------------------------------ ArrowFuncExprNode ---------------------------------
3662
3663RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3664{
3665 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3666}
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003667
mark.lam@apple.com43137872016-03-17 14:58:57 +00003668// ------------------------------ MethodDefinitionNode ---------------------------------
3669
3670RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3671{
3672 return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
3673}
3674
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003675// ------------------------------ YieldExprNode --------------------------------
3676
3677RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3678{
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003679 if (!delegate()) {
3680 RefPtr<RegisterID> arg = nullptr;
3681 if (argument()) {
3682 arg = generator.newTemporary();
3683 generator.emitNode(arg.get(), argument());
3684 } else
3685 arg = generator.emitLoad(nullptr, jsUndefined());
3686 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3687 if (dst == generator.ignoredResult())
3688 return nullptr;
3689 return generator.emitMove(generator.finalDestination(dst), value.get());
3690 }
3691 RefPtr<RegisterID> arg = generator.newTemporary();
3692 generator.emitNode(arg.get(), argument());
3693 RefPtr<RegisterID> value = generator.emitDelegateYield(arg.get(), this);
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003694 if (dst == generator.ignoredResult())
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003695 return nullptr;
3696 return generator.emitMove(generator.finalDestination(dst), value.get());
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003697}
3698
caitp@igalia.com0096c962016-09-23 22:24:27 +00003699// ------------------------------ AwaitExprNode --------------------------------
3700
3701RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3702{
3703 RefPtr<RegisterID> arg = generator.newTemporary();
3704 generator.emitNode(arg.get(), argument());
3705 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3706 if (dst == generator.ignoredResult())
3707 return nullptr;
3708 return generator.emitMove(generator.finalDestination(dst), value.get());
3709}
3710
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003711// ------------------------------ ClassDeclNode ---------------------------------
3712
3713void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3714{
3715 generator.emitNode(dst, m_classDeclaration);
3716}
3717
3718// ------------------------------ ClassExprNode ---------------------------------
3719
3720RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3721{
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003722 if (!m_name.isNull())
sbarati@apple.combdbba812015-12-19 00:19:41 +00003723 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003724
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003725 RefPtr<RegisterID> superclass;
3726 if (m_classHeritage) {
3727 superclass = generator.newTemporary();
3728 generator.emitNode(superclass.get(), m_classHeritage);
3729 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003730
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003731 RefPtr<RegisterID> constructor;
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003732 bool needsHomeObject = false;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003733
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003734 // FIXME: Make the prototype non-configurable & non-writable.
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003735 if (m_constructorExpression) {
3736 ASSERT(m_constructorExpression->isFuncExprNode());
3737 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata();
3738 metadata->setEcmaName(ecmaName());
3739 metadata->setClassSource(m_classSource);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003740 constructor = generator.emitNode(dst, m_constructorExpression);
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003741 if (m_classHeritage) {
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003742 needsHomeObject = true;
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003743 RefPtr<RegisterID> isDerivedConstructor = generator.newTemporary();
3744 generator.emitUnaryOp(op_not, isDerivedConstructor.get(),
3745 generator.emitUnaryOp(op_eq_null, isDerivedConstructor.get(), superclass.get()));
3746 generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), isDerivedConstructor.get(), PropertyNode::Unknown);
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003747 } else if (metadata->superBinding() == SuperBinding::Needed)
3748 needsHomeObject = true;
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003749 } else {
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003750 if (m_classHeritage) {
3751 constructor = generator.finalDestination(dst);
3752 RefPtr<RegisterID> tempRegister = generator.newTemporary();
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003753 Ref<Label> superclassIsNullLabel = generator.newLabel();
3754 Ref<Label> done = generator.newLabel();
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003755
3756 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3757 generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Extends, m_name, ecmaName(), m_classSource);
3758 generator.emitLoad(tempRegister.get(), jsBoolean(true));
3759 generator.emitJump(done.get());
3760 generator.emitLabel(superclassIsNullLabel.get());
3761 generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3762 generator.emitLoad(tempRegister.get(), jsBoolean(false));
3763 generator.emitLabel(done.get());
3764 generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), tempRegister.get(), PropertyNode::Unknown);
3765 } else {
3766 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
3767 ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3768 }
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003769 }
3770
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003771 const auto& propertyNames = generator.propertyNames();
3772 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003773
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003774 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003775 RefPtr<RegisterID> protoParent = generator.newTemporary();
3776 generator.emitLoad(protoParent.get(), jsNull());
3777
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003778 RefPtr<RegisterID> tempRegister = generator.newTemporary();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003779
3780 // FIXME: Throw TypeError if it's a generator function.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003781 Ref<Label> superclassIsUndefinedLabel = generator.newLabel();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003782 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
3783
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003784 Ref<Label> superclassIsNullLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003785 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3786
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003787 Ref<Label> superclassIsObjectLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003788 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003789 generator.emitLabel(superclassIsUndefinedLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003790 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3791 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003792 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
3793
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003794 Ref<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003795 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
keith_miller@apple.com02373132016-01-14 20:45:48 +00003796 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_function, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
3797 generator.emitThrowTypeError(ASCIILiteral("The value of the superclass's prototype property is not an object."));
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003798 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
3799
3800 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003801 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003802 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003803 }
3804
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003805 if (needsHomeObject)
3806 emitPutHomeObject(generator, constructor.get(), prototype.get());
3807
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003808 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003809 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +00003810 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003811
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003812 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +00003813 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003814
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003815 if (m_staticMethods)
3816 generator.emitNode(constructor.get(), m_staticMethods);
3817
3818 if (m_instanceMethods)
3819 generator.emitNode(prototype.get(), m_instanceMethods);
3820
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003821 if (!m_name.isNull()) {
3822 Variable classNameVar = generator.variable(m_name);
3823 RELEASE_ASSERT(classNameVar.isResolved());
3824 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
sbarati@apple.come67fd782016-04-19 01:38:30 +00003825 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003826 generator.popLexicalScope(this);
3827 }
3828
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003829 return generator.moveToDestinationIfNeeded(dst, constructor.get());
3830}
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003831
3832// ------------------------------ ImportDeclarationNode -----------------------
3833
3834void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3835{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003836 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003837}
3838
3839// ------------------------------ ExportAllDeclarationNode --------------------
3840
3841void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3842{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003843 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003844}
3845
3846// ------------------------------ ExportDefaultDeclarationNode ----------------
3847
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003848void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003849{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003850 ASSERT(m_declaration);
3851 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003852}
3853
3854// ------------------------------ ExportLocalDeclarationNode ------------------
3855
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003856void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003857{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003858 ASSERT(m_declaration);
3859 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003860}
3861
3862// ------------------------------ ExportNamedDeclarationNode ------------------
3863
3864void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3865{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003866 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003867}
3868
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003869// ------------------------------ DestructuringAssignmentNode -----------------
3870RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
oliver@apple.comd055db62013-10-02 19:11:04 +00003871{
3872 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
3873 return result;
3874 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
3875 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00003876 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003877 return generator.moveToDestinationIfNeeded(dst, initializer.get());
3878}
3879
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003880static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
3881{
3882 ASSERT(defaultValue);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003883 Ref<Label> isNotUndefined = generator.newLabel();
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003884 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
3885 generator.emitNode(maybeUndefined, defaultValue);
3886 generator.emitLabel(isNotUndefined.get());
3887}
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003888
oliver@apple.com47784d62013-10-25 21:31:36 +00003889void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003890{
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003891 RefPtr<RegisterID> iterator = generator.newTemporary();
3892 {
3893 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
3894 CallArguments args(generator, nullptr);
3895 generator.emitMove(args.thisRegister(), rhs);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003896 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003897 }
3898
utatane.tea@gmail.coma5c94332015-06-23 00:51:44 +00003899 if (m_targetPatterns.isEmpty()) {
3900 generator.emitIteratorClose(iterator.get(), this);
3901 return;
3902 }
3903
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003904 RefPtr<RegisterID> done;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003905 for (auto& target : m_targetPatterns) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003906 switch (target.bindingType) {
3907 case BindingType::Elision:
3908 case BindingType::Element: {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003909 Ref<Label> iterationSkipped = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003910 if (!done)
3911 done = generator.newTemporary();
3912 else
3913 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003914
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003915 RefPtr<RegisterID> value = generator.newTemporary();
3916 generator.emitIteratorNext(value.get(), iterator.get(), this);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003917 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003918 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
3919 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003920
3921 {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003922 Ref<Label> valueIsSet = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003923 generator.emitJump(valueIsSet.get());
3924 generator.emitLabel(iterationSkipped.get());
3925 generator.emitLoad(value.get(), jsUndefined());
3926 generator.emitLabel(valueIsSet.get());
3927 }
3928
3929 if (target.bindingType == BindingType::Element) {
3930 if (target.defaultValue)
3931 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
3932 target.pattern->bindValue(generator, value.get());
3933 }
3934 break;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003935 }
3936
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003937 case BindingType::RestElement: {
3938 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
3939
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003940 Ref<Label> iterationDone = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003941 if (!done)
3942 done = generator.newTemporary();
3943 else
3944 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3945
3946 RefPtr<RegisterID> index = generator.newTemporary();
3947 generator.emitLoad(index.get(), jsNumber(0));
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003948 Ref<Label> loopStart = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003949 generator.emitLabel(loopStart.get());
3950
3951 RefPtr<RegisterID> value = generator.newTemporary();
3952 generator.emitIteratorNext(value.get(), iterator.get(), this);
3953 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
3954 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3955 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
3956
3957 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
3958 generator.emitInc(index.get());
3959 generator.emitJump(loopStart.get());
3960
3961 generator.emitLabel(iterationDone.get());
3962 target.pattern->bindValue(generator, array.get());
3963 break;
3964 }
3965 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003966 }
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003967
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003968 Ref<Label> iteratorClosed = generator.newLabel();
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003969 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
3970 generator.emitIteratorClose(iterator.get(), this);
3971 generator.emitLabel(iteratorClosed.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003972}
3973
3974RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
3975{
oliver@apple.comd055db62013-10-02 19:11:04 +00003976 if (!rhs->isSimpleArray())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003977 return nullptr;
3978
3979 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
3980 Vector<ExpressionNode*> elements;
3981 for (; elementNodes; elementNodes = elementNodes->next()) {
3982 ExpressionNode* value = elementNodes->value();
3983 if (value->isSpreadExpression())
3984 return nullptr;
3985 elements.append(value);
3986 }
oliver@apple.com47784d62013-10-25 21:31:36 +00003987
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003988 RefPtr<RegisterID> resultRegister;
3989 if (dst && dst != generator.ignoredResult())
3990 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00003991 if (m_targetPatterns.size() != elements.size())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003992 return nullptr;
oliver@apple.comd055db62013-10-02 19:11:04 +00003993 Vector<RefPtr<RegisterID>> registers;
3994 registers.reserveCapacity(m_targetPatterns.size());
3995 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3996 registers.uncheckedAppend(generator.newTemporary());
3997 generator.emitNode(registers.last().get(), elements[i]);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003998 if (m_targetPatterns[i].defaultValue)
3999 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00004000 if (resultRegister)
4001 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00004002 }
4003
4004 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00004005 if (m_targetPatterns[i].pattern)
4006 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00004007 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00004008 if (resultRegister)
4009 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00004010 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00004011}
4012
4013void ArrayPatternNode::toString(StringBuilder& builder) const
4014{
4015 builder.append('[');
4016 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00004017 const auto& target = m_targetPatterns[i];
4018
4019 switch (target.bindingType) {
4020 case BindingType::Elision:
oliver@apple.comd055db62013-10-02 19:11:04 +00004021 builder.append(',');
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00004022 break;
4023
4024 case BindingType::Element:
4025 target.pattern->toString(builder);
4026 if (i < m_targetPatterns.size() - 1)
4027 builder.append(',');
4028 break;
4029
4030 case BindingType::RestElement:
commit-queue@webkit.org57101852016-08-12 00:33:47 +00004031 builder.appendLiteral("...");
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00004032 target.pattern->toString(builder);
4033 break;
oliver@apple.comd055db62013-10-02 19:11:04 +00004034 }
oliver@apple.comd055db62013-10-02 19:11:04 +00004035 }
4036 builder.append(']');
4037}
4038
4039void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4040{
4041 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.comc497d152015-07-17 18:48:30 +00004042 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
oliver@apple.comd055db62013-10-02 19:11:04 +00004043 node->collectBoundIdentifiers(identifiers);
4044 }
4045}
4046
4047void ObjectPatternNode::toString(StringBuilder& builder) const
4048{
4049 builder.append('{');
4050 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00004051 if (m_targetPatterns[i].wasString)
akling@apple.coma9904fb2015-05-08 08:44:23 +00004052 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00004053 else
oliver@apple.comd055db62013-10-02 19:11:04 +00004054 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00004055 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00004056 m_targetPatterns[i].pattern->toString(builder);
4057 if (i < m_targetPatterns.size() - 1)
4058 builder.append(',');
4059 }
4060 builder.append('}');
4061}
4062
oliver@apple.com47784d62013-10-25 21:31:36 +00004063void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00004064{
commit-queue@webkit.org4d3e0c22015-12-01 20:11:20 +00004065 generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
commit-queue@webkit.org2162b032017-03-10 02:00:33 +00004066
commit-queue@webkit.org97475e72017-03-16 12:58:14 +00004067 IdentifierSet excludedSet;
commit-queue@webkit.org38980282015-11-25 01:43:14 +00004068
commit-queue@webkit.org2162b032017-03-10 02:00:33 +00004069 for (const auto& target : m_targetPatterns) {
4070 if (target.bindingType == BindingType::Element) {
4071 RefPtr<RegisterID> temp = generator.newTemporary();
4072 if (!target.propertyExpression) {
4073
4074 // Should not emit get_by_id for indexed ones.
4075 std::optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
4076 if (!optionalIndex)
4077 generator.emitGetById(temp.get(), rhs, target.propertyName);
4078 else {
4079 RefPtr<RegisterID> pIndex = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
4080 generator.emitGetByVal(temp.get(), rhs, pIndex.get());
4081 }
4082 } else {
4083 RefPtr<RegisterID> propertyName = generator.emitNode(target.propertyExpression);
4084 generator.emitGetByVal(temp.get(), rhs, propertyName.get());
4085 }
4086
4087 if (UNLIKELY(m_containsRestElement))
4088 excludedSet.add(target.propertyName.impl());
4089
4090 if (target.defaultValue)
4091 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
4092 target.pattern->bindValue(generator, temp.get());
4093 } else {
4094 RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
4095
4096 RefPtr<RegisterID> newObject = generator.emitNewObject(generator.newTemporary());
4097
4098 // load and call @copyDataProperties
4099 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
4100
4101 RefPtr<RegisterID> scope = generator.newTemporary();
4102 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
4103 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4104
4105 CallArguments args(generator, nullptr, 3);
4106 unsigned argumentCount = 0;
4107 generator.emitLoad(args.thisRegister(), jsUndefined());
4108 generator.emitMove(args.argumentRegister(argumentCount++), newObject.get());
4109 generator.emitMove(args.argumentRegister(argumentCount++), rhs);
4110 generator.emitMove(args.argumentRegister(argumentCount++), excludedSetReg.get());
4111
4112 RefPtr<RegisterID> result = generator.newTemporary();
4113 generator.emitCall(result.get(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4114 target.pattern->bindValue(generator, result.get());
4115 }
oliver@apple.comd055db62013-10-02 19:11:04 +00004116 }
4117}
4118
4119void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4120{
4121 for (size_t i = 0; i < m_targetPatterns.size(); i++)
4122 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
4123}
4124
oliver@apple.com47784d62013-10-25 21:31:36 +00004125void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00004126{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004127 Variable var = generator.variable(m_boundProperty);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004128 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004129 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004130 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4131 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004132 if (isReadOnly) {
4133 generator.emitReadOnlyExceptionIfNeeded(var);
4134 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00004135 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004136 generator.emitMove(local, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00004137 generator.emitProfileType(local, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004138 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004139 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00004140 return;
4141 }
4142 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00004143 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00004144 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00004145 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004146 if (m_bindingContext == AssignmentContext::AssignmentExpression)
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00004147 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004148 if (isReadOnly) {
4149 generator.emitReadOnlyExceptionIfNeeded(var);
4150 return;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004151 }
mark.lam@apple.com4a23c922017-03-11 01:38:22 +00004152 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00004153 generator.emitProfileType(value, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004154 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004155 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00004156 return;
4157}
4158
4159void BindingNode::toString(StringBuilder& builder) const
4160{
4161 builder.append(m_boundProperty.string());
4162}
4163
4164void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4165{
4166 identifiers.append(m_boundProperty);
4167}
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004168
4169void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
4170{
4171}
4172
4173void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
4174{
4175 if (m_assignmentTarget->isResolveNode()) {
4176 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
4177 Variable var = generator.variable(lhs->identifier());
4178 bool isReadOnly = var.isReadOnly();
4179 if (RegisterID* local = var.local()) {
4180 generator.emitTDZCheckIfNecessary(var, local, nullptr);
4181
4182 if (isReadOnly)
4183 generator.emitReadOnlyExceptionIfNeeded(var);
4184 else {
4185 generator.invalidateForInContextForLocal(local);
4186 generator.moveToDestinationIfNeeded(local, value);
4187 generator.emitProfileType(local, divotStart(), divotEnd());
4188 }
4189 return;
4190 }
4191 if (generator.isStrictMode())
4192 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4193 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
4194 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
4195 if (isReadOnly) {
4196 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
4197 if (threwException)
4198 return;
4199 }
4200 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4201 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00004202 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004203 generator.emitProfileType(value, var, divotStart(), divotEnd());
4204 }
4205 } else if (m_assignmentTarget->isDotAccessorNode()) {
4206 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
4207 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4208 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00004209 if (lhs->base()->isSuperNode()) {
4210 RefPtr<RegisterID> thisValue = generator.ensureThis();
4211 generator.emitPutById(base.get(), thisValue.get(), lhs->identifier(), value);
4212 } else
4213 generator.emitPutById(base.get(), lhs->identifier(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004214 generator.emitProfileType(value, divotStart(), divotEnd());
4215 } else if (m_assignmentTarget->isBracketAccessorNode()) {
4216 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
4217 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4218 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(lhs->subscript(), true, false);
4219 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00004220 if (lhs->base()->isSuperNode()) {
4221 RefPtr<RegisterID> thisValue = generator.ensureThis();
4222 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
4223 } else
4224 generator.emitPutByVal(base.get(), property.get(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004225 generator.emitProfileType(value, divotStart(), divotEnd());
4226 }
4227}
4228
4229void AssignmentElementNode::toString(StringBuilder& builder) const
4230{
4231 if (m_assignmentTarget->isResolveNode())
4232 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
4233}
4234
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004235void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4236{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004237 m_pattern->collectBoundIdentifiers(identifiers);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004238}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004239
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004240void RestParameterNode::toString(StringBuilder& builder) const
4241{
commit-queue@webkit.org57101852016-08-12 00:33:47 +00004242 builder.appendLiteral("...");
sbarati@apple.com6a686122016-08-03 07:50:40 +00004243 m_pattern->toString(builder);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004244}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004245
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004246void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
4247{
4248 RELEASE_ASSERT_NOT_REACHED();
4249}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004250
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004251void RestParameterNode::emit(BytecodeGenerator& generator)
4252{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004253 RefPtr<RegisterID> temp = generator.newTemporary();
4254 generator.emitRestParameter(temp.get(), m_numParametersToSkip);
4255 m_pattern->bindValue(generator, temp.get());
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004256}
4257
4258
oliver@apple.com72f8a822013-10-17 01:02:34 +00004259RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4260{
4261 RELEASE_ASSERT_NOT_REACHED();
4262 return 0;
4263}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00004264
commit-queue@webkit.org97475e72017-03-16 12:58:14 +00004265RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
4266{
4267 RefPtr<RegisterID> src = generator.newTemporary();
4268 generator.emitNode(src.get(), m_expression);
4269 IdentifierSet excludedSet;
4270
4271 RefPtr<RegisterID> excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
4272
4273 // load and call @copyDataProperties
4274 auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
4275
4276 RefPtr<RegisterID> scope = generator.newTemporary();
4277 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
4278 RefPtr<RegisterID> copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
4279
4280 CallArguments args(generator, nullptr, 3);
4281 unsigned argumentCount = 0;
4282 generator.emitLoad(args.thisRegister(), jsUndefined());
4283 generator.emitMove(args.argumentRegister(argumentCount++), dst);
4284 generator.emitMove(args.argumentRegister(argumentCount++), src.get());
4285 generator.emitMove(args.argumentRegister(argumentCount++), excludedSetReg.get());
4286
4287 generator.emitCall(generator.newTemporary(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
4288
4289 return 0;
4290}
4291
mjs@apple.comaed3cef2009-12-09 01:29:52 +00004292} // namespace JSC