blob: f8f08b8e044a4ce1eff5f06607d86fafd14ead33 [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.com4b79ce72016-03-11 21:08:08 +00004* Copyright (C) 2003-2009, 2012-2013, 2015-2016 Apple Inc. All rights reserved.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00005* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +00008 * Copyright (C) 2012 Igalia, S.L.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00009*
10* This library is free software; you can redistribute it and/or
11* modify it under the terms of the GNU Library General Public
12* License as published by the Free Software Foundation; either
13* version 2 of the License, or (at your option) any later version.
14*
15* This library is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18* Library General Public License for more details.
19*
20* You should have received a copy of the GNU Library General Public License
21* along with this library; see the file COPYING.LIB. If not, write to
22* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23* Boston, MA 02110-1301, USA.
24*
25*/
26
27#include "config.h"
28#include "Nodes.h"
oliver@apple.comd04e0a02014-02-01 01:37:59 +000029#include "NodeConstructors.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000030
oliver@apple.comc422ba02014-02-27 23:25:29 +000031#include "BuiltinNames.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000032#include "BytecodeGenerator.h"
33#include "CallFrame.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000034#include "JIT.h"
joepeck@webkit.org7e07f392016-09-22 18:59:47 +000035#include "JSCInlines.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000036#include "JSFunction.h"
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +000037#include "JSGeneratorFunction.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000038#include "JSGlobalObject.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000039#include "LabelScope.h"
40#include "Lexer.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000041#include "Parser.h"
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +000042#include "StackAlignment.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000043#include <wtf/Assertions.h>
mjs@apple.comaed3cef2009-12-09 01:29:52 +000044#include <wtf/Threading.h>
joepeck@webkit.org7e07f392016-09-22 18:59:47 +000045#include <wtf/text/StringBuilder.h>
mjs@apple.comaed3cef2009-12-09 01:29:52 +000046
47using namespace WTF;
48
49namespace JSC {
50
51/*
52 Details of the emitBytecode function.
53
54 Return value: The register holding the production's value.
55 dst: An optional parameter specifying the most efficient destination at
56 which to store the production's value. The callee must honor dst.
57
58 The dst argument provides for a crude form of copy propagation. For example,
59
60 x = 1
61
62 becomes
63
64 load r[x], 1
65
66 instead of
67
68 load r0, 1
69 mov r[x], r0
70
71 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
72*/
73
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +000074void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +000075{
76 RegisterID* result = generator.emitNode(this);
77 if (fallThroughMode == FallThroughMeansTrue)
78 generator.emitJumpIfFalse(result, falseTarget);
79 else
80 generator.emitJumpIfTrue(result, trueTarget);
81}
82
mjs@apple.comaed3cef2009-12-09 01:29:52 +000083// ------------------------------ ThrowableExpressionData --------------------------------
84
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000085RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000086{
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +000087 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com4920ae92010-11-12 03:06:07 +000088 generator.emitThrowReferenceError(message);
89 return generator.newTemporary();
mjs@apple.comaed3cef2009-12-09 01:29:52 +000090}
91
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000092// ------------------------------ ConstantNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +000093
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +000094void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000095{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000096 TriState value = jsValue(generator).pureToBoolean();
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +000097
98 if (UNLIKELY(needsDebugHook())) {
99 if (value != MixedTriState)
100 generator.emitDebugHook(this);
101 }
102
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000103 if (value == MixedTriState)
104 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
105 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
106 generator.emitJump(trueTarget);
107 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
108 generator.emitJump(falseTarget);
109
110 // All other cases are unconditional fall-throughs, like "if (true)".
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000111}
112
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000113RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000114{
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000115 if (dst == generator.ignoredResult())
116 return 0;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000117 return generator.emitLoad(dst, jsValue(generator));
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000118}
119
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000120JSValue StringNode::jsValue(BytecodeGenerator& generator) const
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000121{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000122 return generator.addStringConstant(m_value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000123}
124
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000125// ------------------------------ NumberNode ----------------------------------
126
127RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
128{
129 if (dst == generator.ignoredResult())
130 return nullptr;
131 return generator.emitLoad(dst, jsValue(generator), isIntegerNode() ? SourceCodeRepresentation::Integer : SourceCodeRepresentation::Double);
132}
133
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000134// ------------------------------ RegExpNode -----------------------------------
135
136RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
137{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000138 if (dst == generator.ignoredResult())
139 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000140 return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string())));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000141}
142
143// ------------------------------ ThisNode -------------------------------------
144
145RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
146{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000147 generator.ensureThis();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000148 if (dst == generator.ignoredResult())
149 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000150
151 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000152 static const unsigned thisLength = 4;
153 generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000154 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000155}
156
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000157// ------------------------------ SuperNode -------------------------------------
158
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000159static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000160{
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000161 if (generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {
162 RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000163 return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().builtinNames().homeObjectPrivateName());
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000164 }
165
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000166 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000167 callee.setIndex(CallFrameSlot::callee);
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000168 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().builtinNames().homeObjectPrivateName());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000169}
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000170
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000171static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
172{
173 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000174 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
175}
176
sbarati@apple.com23315d62016-05-09 20:17:23 +0000177static RegisterID* emitGetSuperFunctionForConstruct(BytecodeGenerator& generator)
178{
179 if (generator.isDerivedConstructorContext())
180 return generator.emitGetById(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(), generator.propertyNames().underscoreProto);
181
182 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000183 callee.setIndex(CallFrameSlot::callee);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000184 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().underscoreProto);
185}
186
187RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
188{
189 RegisterID* result = emitSuperBaseForCallee(generator);
190 return generator.moveToDestinationIfNeeded(generator.finalDestination(dst), result);
191}
192
utatane.tea@gmail.com5e639122017-01-09 22:02:47 +0000193// ------------------------------ ImportNode -------------------------------------
194
195RegisterID* ImportNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
196{
197 RefPtr<RegisterID> importModule = generator.emitGetGlobalPrivate(generator.newTemporary(), generator.propertyNames().builtinNames().importModulePrivateName());
198 CallArguments arguments(generator, nullptr, 1);
199 generator.emitLoad(arguments.thisRegister(), jsUndefined());
200 generator.emitNode(arguments.argumentRegister(0), m_expr);
201 return generator.emitCall(generator.finalDestination(dst, importModule.get()), importModule.get(), NoExpectedFunction, arguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
202}
203
commit-queue@webkit.org17f99e42015-07-21 18:18:42 +0000204// ------------------------------ NewTargetNode ----------------------------------
205
206RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
207{
208 if (dst == generator.ignoredResult())
209 return nullptr;
210
211 return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
212}
213
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000214// ------------------------------ ResolveNode ----------------------------------
215
216bool ResolveNode::isPure(BytecodeGenerator& generator) const
217{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000218 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000219}
220
221RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
222{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000223 Variable var = generator.variable(m_ident);
224 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000225 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000226 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000227 return nullptr;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000228
229 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000230 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000231 }
232
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000233 JSTextPosition divot = m_start + m_ident.length();
234 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000235 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000236 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000237 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000238 generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000239 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000240 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000241}
242
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000243// ------------------------------ TemplateStringNode -----------------------------------
244
245RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
246{
247 if (dst == generator.ignoredResult())
248 return nullptr;
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000249 ASSERT(cooked());
250 return generator.emitLoad(dst, JSValue(generator.addStringConstant(*cooked())));
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000251}
252
253// ------------------------------ TemplateLiteralNode -----------------------------------
254
255RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
256{
257 if (!m_templateExpressions) {
258 TemplateStringNode* templateString = m_templateStrings->value();
259 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
260 return generator.emitNode(dst, templateString);
261 }
262
263 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
264
265 TemplateStringListNode* templateString = m_templateStrings;
266 TemplateExpressionListNode* templateExpression = m_templateExpressions;
267 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
268 // Evaluate TemplateString.
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000269 ASSERT(templateString->value()->cooked());
270 if (!templateString->value()->cooked()->isEmpty()) {
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000271 temporaryRegisters.append(generator.newTemporary());
272 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
273 }
274
275 // Evaluate Expression.
276 temporaryRegisters.append(generator.newTemporary());
277 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
278 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
279 }
280
281 // Evaluate tail TemplateString.
utatane.tea@gmail.coma10944d2017-01-28 03:09:12 +0000282 ASSERT(templateString->value()->cooked());
283 if (!templateString->value()->cooked()->isEmpty()) {
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000284 temporaryRegisters.append(generator.newTemporary());
285 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
286 }
287
oliver@apple.com1aec7c72016-06-13 23:17:00 +0000288 if (temporaryRegisters.size() == 1)
289 return generator.emitToString(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get());
290
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000291 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
292}
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000293
294// ------------------------------ TaggedTemplateNode -----------------------------------
295
296RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
297{
298 ExpectedFunction expectedFunction = NoExpectedFunction;
299 RefPtr<RegisterID> tag = nullptr;
300 RefPtr<RegisterID> base = nullptr;
301 if (!m_tag->isLocation()) {
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000302 tag = generator.newTemporary();
303 tag = generator.emitNode(tag.get(), m_tag);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000304 } else if (m_tag->isResolveNode()) {
305 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
306 const Identifier& identifier = resolve->identifier();
307 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
308
309 Variable var = generator.variable(identifier);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000310 if (RegisterID* local = var.local()) {
311 generator.emitTDZCheckIfNecessary(var, local, nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000312 tag = generator.emitMove(generator.newTemporary(), local);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000313 } else {
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000314 tag = generator.newTemporary();
315 base = generator.newTemporary();
316
317 JSTextPosition newDivot = divotStart() + identifier.length();
318 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
319 generator.moveToDestinationIfNeeded(base.get(), generator.emitResolveScope(base.get(), var));
320 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000321 generator.emitTDZCheckIfNecessary(var, tag.get(), nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000322 }
323 } else if (m_tag->isBracketAccessorNode()) {
324 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000325 base = generator.newTemporary();
326 base = generator.emitNode(base.get(), bracket->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000327 RefPtr<RegisterID> property = generator.emitNode(bracket->subscript());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000328 if (bracket->base()->isSuperNode()) {
329 RefPtr<RegisterID> thisValue = generator.ensureThis();
330 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
331 } else
332 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000333 } else {
334 ASSERT(m_tag->isDotAccessorNode());
335 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000336 base = generator.newTemporary();
337 base = generator.emitNode(base.get(), dot->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000338 if (dot->base()->isSuperNode()) {
339 RefPtr<RegisterID> thisValue = generator.ensureThis();
340 tag = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), dot->identifier());
341 } else
342 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000343 }
344
345 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(generator.newTemporary(), this);
346
347 unsigned expressionsCount = 0;
348 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
349 ++expressionsCount;
350
351 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
352 if (base)
353 generator.emitMove(callArguments.thisRegister(), base.get());
354 else
355 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
356
357 unsigned argumentIndex = 0;
358 generator.emitMove(callArguments.argumentRegister(argumentIndex++), templateObject.get());
359 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
360 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
361
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000362 return generator.emitCallInTailPosition(generator.finalDestination(dst, tag.get()), tag.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000363}
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000364
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000365// ------------------------------ ArrayNode ------------------------------------
366
367RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
368{
369 // FIXME: Should we put all of this code into emitNewArray?
370
371 unsigned length = 0;
372 ElementNode* firstPutElement;
373 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000374 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000375 break;
376 ++length;
377 }
378
379 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000380 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000381
sbarati@apple.com99ed4792016-11-12 02:58:11 +0000382 if (firstPutElement && firstPutElement->value()->isSpreadExpression()) {
383 bool hasElision = false;
384 for (ElementNode* node = m_element; node; node = node->next()) {
385 if (!!node->elision()) {
386 hasElision = true;
387 break;
388 }
389 }
390 if (!!m_elision)
391 hasElision = true;
392
393 if (!hasElision)
394 return generator.emitNewArrayWithSpread(generator.finalDestination(dst), m_element);
395 }
396
oliver@apple.coma991d692011-06-14 23:39:25 +0000397 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000398 ElementNode* n = firstPutElement;
399 for (; n; n = n->next()) {
400 if (n->value()->isSpreadExpression())
401 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000402 RegisterID* value = generator.emitNode(n->value());
403 length += n->elision();
404 generator.emitPutByIndex(array.get(), length++, value);
405 }
406
407 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000408 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000409 generator.emitPutById(array.get(), generator.propertyNames().length, value);
410 }
411
412 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000413
414handleSpread:
415 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
416 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
417 {
oliver@apple.come050d642013-10-19 00:09:28 +0000418 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000419 generator.emitInc(index.get());
420 };
421 for (; n; n = n->next()) {
422 if (n->elision())
423 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
424 if (n->value()->isSpreadExpression()) {
425 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
426 generator.emitEnumeration(spread, spread->expression(), spreader);
427 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000428 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000429 generator.emitInc(index.get());
430 }
431 }
432
433 if (m_elision) {
434 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
435 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
436 }
437 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000438}
439
440bool ArrayNode::isSimpleArray() const
441{
442 if (m_elision || m_optional)
443 return false;
444 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
445 if (ptr->elision())
446 return false;
commit-queue@webkit.org1a78b432016-09-15 01:14:45 +0000447 if (ptr->value()->isSpreadExpression())
448 return false;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000449 }
450 return true;
451}
452
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000453ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000454{
455 ASSERT(!m_elision && !m_optional);
456 ElementNode* ptr = m_element;
457 if (!ptr)
458 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000459 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000460 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000461 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000462 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000463 ArgumentListNode* tail = head;
464 ptr = ptr->next();
465 for (; ptr; ptr = ptr->next()) {
466 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000467 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000468 }
469 return head;
470}
471
472// ------------------------------ ObjectLiteralNode ----------------------------
473
474RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
475{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000476 if (!m_list) {
477 if (dst == generator.ignoredResult())
478 return 0;
479 return generator.emitNewObject(generator.finalDestination(dst));
480 }
481 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
482 generator.emitNode(newObj.get(), m_list);
483 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000484}
485
486// ------------------------------ PropertyListNode -----------------------------
487
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000488static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
489{
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000490 generator.emitPutById(function, generator.propertyNames().builtinNames().homeObjectPrivateName(), homeObject);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000491}
492
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000493RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
494{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000495 // Fast case: this loop just handles regular value properties.
496 PropertyListNode* p = this;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000497 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000498 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000499
500 // Were there any get/set properties?
501 if (p) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000502 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
503 // a computed property, just emit everything as that may override previous values.
504 bool hasComputedProperty = false;
505
barraclough@apple.com09a55682012-01-30 18:28:39 +0000506 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000507 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000508 GetterSetterMap map;
509
510 // Build a map, pairing get/set values together.
511 for (PropertyListNode* q = p; q; q = q->m_next) {
512 PropertyNode* node = q->m_node;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000513 if (node->m_type & PropertyNode::Computed) {
514 hasComputedProperty = true;
515 break;
516 }
517 if (node->m_type & PropertyNode::Constant)
barraclough@apple.com09a55682012-01-30 18:28:39 +0000518 continue;
519
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000520 // Duplicates are possible.
521 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
oliver@apple.com72d38322013-10-21 19:23:24 +0000522 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000523 if (!result.isNewEntry) {
524 if (result.iterator->value.first->m_type == node->m_type)
525 result.iterator->value.first = node;
526 else
527 result.iterator->value.second = node;
528 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000529 }
530
531 // Iterate over the remaining properties in the list.
532 for (; p; p = p->m_next) {
533 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000534
535 // Handle regular values.
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000536 if (node->m_type & PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000537 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000538 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000539 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000540
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000541 RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000542 bool needsSuperBinding = node->needsSuperBinding();
543 if (needsSuperBinding)
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000544 emitPutHomeObject(generator, value.get(), dst);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000545
546 unsigned attributes = node->isClassProperty() ? (Accessor | DontEnum) : Accessor;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000547
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000548 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
549
550 // This is a get/set property which may be overridden by a computed property later.
551 if (hasComputedProperty) {
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000552 // Computed accessors.
553 if (node->m_type & PropertyNode::Computed) {
554 RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000555 generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000556 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000557 generator.emitPutGetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000558 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000559 generator.emitPutSetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000560 continue;
561 }
562
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000563 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000564 generator.emitPutGetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000565 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000566 generator.emitPutSetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000567 continue;
568 }
569
570 // This is a get/set property pair.
oliver@apple.com72d38322013-10-21 19:23:24 +0000571 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000572 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000573 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000574
575 // Was this already generated as a part of its partner?
576 if (pair.second == node)
577 continue;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000578
barraclough@apple.com09a55682012-01-30 18:28:39 +0000579 // Generate the paired node now.
580 RefPtr<RegisterID> getterReg;
581 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000582 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000583
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000584 if (node->m_type & PropertyNode::Getter) {
barraclough@apple.com09a55682012-01-30 18:28:39 +0000585 getterReg = value;
586 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000587 ASSERT(pair.second->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000588 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000589 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000590 } else {
591 setterReg = generator.newTemporary();
592 generator.emitLoad(setterReg.get(), jsUndefined());
593 }
594 } else {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000595 ASSERT(node->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000596 setterReg = value;
597 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000598 ASSERT(pair.second->m_type & PropertyNode::Getter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000599 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000600 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000601 } else {
602 getterReg = generator.newTemporary();
603 generator.emitLoad(getterReg.get(), jsUndefined());
604 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000605 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000606
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000607 ASSERT(!pair.second || needsSuperBinding == pair.second->needsSuperBinding());
608 if (needsSuperBinding && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000609 emitPutHomeObject(generator, secondReg, dst);
610
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000611 generator.emitPutGetterSetter(dst, *node->name(), attributes, getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000612 }
613 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000614
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000615 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000616}
617
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000618void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
619{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000620 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000621 if (node.needsSuperBinding())
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000622 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000623
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000624 if (node.isClassProperty()) {
625 ASSERT(node.needsSuperBinding());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000626 RefPtr<RegisterID> propertyNameRegister;
627 if (node.name())
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000628 propertyNameRegister = generator.emitLoad(nullptr, *node.name());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000629 else
630 propertyNameRegister = generator.emitNode(node.m_expression);
631
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000632 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +0000633 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000634 return;
635 }
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000636 if (const auto* identifier = node.name()) {
utatane.tea@gmail.com43926962016-11-27 06:08:16 +0000637 std::optional<uint32_t> optionalIndex = parseIndex(*identifier);
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000638 if (!optionalIndex) {
639 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
640 return;
641 }
642
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000643 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000644 generator.emitDirectPutByVal(newObj, index.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000645 return;
646 }
647 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000648 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000649 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000650}
651
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000652// ------------------------------ BracketAccessorNode --------------------------------
653
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000654static bool isNonIndexStringElement(ExpressionNode& element)
655{
656 return element.isString() && !parseIndex(static_cast<StringNode&>(element).value());
657}
658
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000659RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
660{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000661 if (m_base->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000662 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
663 RefPtr<RegisterID> thisValue = generator.ensureThis();
664 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000665
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000666 if (isNonIndexStringElement(*m_subscript)) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000667 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000668 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000669 generator.emitGetById(finalDest.get(), superBase.get(), thisValue.get(), id);
670 } else {
671 RefPtr<RegisterID> subscript = generator.emitNode(m_subscript);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000672 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000673 generator.emitGetByVal(finalDest.get(), superBase.get(), thisValue.get(), subscript.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000674 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000675
sbarati@apple.com23315d62016-05-09 20:17:23 +0000676 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
677 return finalDest.get();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000678 }
679
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000680 RegisterID* ret;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000681 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000682
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000683 if (isNonIndexStringElement(*m_subscript)) {
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000684 RefPtr<RegisterID> base = generator.emitNode(m_base);
commit-queue@webkit.org31924df2016-10-14 06:31:40 +0000685 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000686 ret = generator.emitGetById(finalDest.get(), base.get(), static_cast<StringNode*>(m_subscript)->value());
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000687 } else {
688 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
689 RegisterID* property = generator.emitNode(m_subscript);
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.emitGetByVal(finalDest.get(), base.get(), property);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000692 }
693
sbarati@apple.com23315d62016-05-09 20:17:23 +0000694 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000695 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000696}
697
698// ------------------------------ DotAccessorNode --------------------------------
699
700RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
701{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000702 bool baseIsSuper = m_base->isSuperNode();
703 RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000704 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000705 RegisterID* finalDest = generator.finalDestination(dst);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000706 RegisterID* ret;
707 if (baseIsSuper) {
708 RefPtr<RegisterID> thisValue = generator.ensureThis();
709 ret = generator.emitGetById(finalDest, base.get(), thisValue.get(), m_ident);
710 } else
711 ret = generator.emitGetById(finalDest, base.get(), m_ident);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000712 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000713 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000714}
715
716// ------------------------------ ArgumentListNode -----------------------------
717
718RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
719{
720 ASSERT(m_expr);
721 return generator.emitNode(dst, m_expr);
722}
723
724// ------------------------------ NewExprNode ----------------------------------
725
726RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
727{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000728 ExpectedFunction expectedFunction;
729 if (m_expr->isResolveNode())
730 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
731 else
732 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000733 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000734 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000735 CallArguments callArguments(generator, m_args);
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000736 generator.emitMove(callArguments.thisRegister(), func.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000737 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000738}
739
oliver@apple.com72f8a822013-10-17 01:02:34 +0000740CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000741 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000742 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000743{
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000744 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000745 if (argumentsNode) {
746 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
747 ++argumentCountIncludingThis;
748 }
749
750 m_argv.grow(argumentCountIncludingThis);
751 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
752 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000753 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 +0000754 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000755
756 // We need to ensure that the frame size is stack-aligned
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000757 while ((CallFrame::headerSizeInRegisters + m_argv.size()) % stackAlignmentRegisters()) {
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000758 m_argv.insert(0, generator.newTemporary());
759 m_padding++;
760 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000761
762 while (stackOffset() % stackAlignmentRegisters()) {
763 m_argv.insert(0, generator.newTemporary());
764 m_padding++;
765 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000766}
767
768// ------------------------------ EvalFunctionCallNode ----------------------------------
769
770RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
771{
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000772 // We need try to load 'this' before call eval in constructor, because 'this' can created by 'super' in some of the arrow function
773 // var A = class A {
774 // constructor () { this.id = 'A'; }
775 // }
776 //
777 // var B = class B extend A {
778 // constructor () {
779 // var arrow = () => super();
780 // arrow();
781 // eval("this.id = 'B'");
782 // }
783 // }
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000784 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000785 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
786
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000787 Variable var = generator.variable(generator.propertyNames().eval);
788 if (RegisterID* local = var.local()) {
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000789 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000790 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000791 CallArguments callArguments(generator, m_args);
792 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000793 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
oliver@apple.com58c86752013-07-25 04:02:40 +0000794 }
795
796 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000797 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000798 JSTextPosition newDivot = divotStart() + 4;
799 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000800 generator.moveToDestinationIfNeeded(
801 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000802 generator.emitResolveScope(callArguments.thisRegister(), var));
803 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000804 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000805 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000806}
807
808// ------------------------------ FunctionCallValueNode ----------------------------------
809
810RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
811{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000812 if (m_expr->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000813 RefPtr<RegisterID> func = emitGetSuperFunctionForConstruct(generator);
814 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
815 CallArguments callArguments(generator, m_args);
816
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000817 ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000818 ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000819 generator.emitMove(callArguments.thisRegister(), generator.newTarget());
820 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000821
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000822 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000823 bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
824
825 if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction()))
826 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
827
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +0000828 Ref<Label> thisIsEmptyLabel = generator.newLabel();
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000829 generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get());
830 generator.emitThrowReferenceError(ASCIILiteral("'super()' can't be called more than once in a constructor."));
831 generator.emitLabel(thisIsEmptyLabel.get());
832
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000833 generator.emitMove(generator.thisRegister(), ret);
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000834
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000835 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor)
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000836 generator.emitPutThisToArrowFunctionContextScope();
commit-queue@webkit.orgabdc6172016-02-24 20:46:44 +0000837
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000838 return ret;
839 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000840 RefPtr<RegisterID> func = generator.emitNode(m_expr);
841 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
842 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000843 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000844 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000845 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000846 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000847}
848
849// ------------------------------ FunctionCallResolveNode ----------------------------------
850
851RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
852{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000853 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000854
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000855 Variable var = generator.variable(m_ident);
856 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000857 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000858 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000859 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000860 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000861 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000862 // This passes NoExpectedFunction because we expect that if the function is in a
863 // local variable, then it's not one of our built-in constructors.
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000864 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000865 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000866 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000867 }
868
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000869 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000870 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000871 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000872
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000873 JSTextPosition newDivot = divotStart() + m_ident.length();
874 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000875 generator.moveToDestinationIfNeeded(
876 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000877 generator.emitResolveScope(callArguments.thisRegister(), var));
878 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000879 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000880 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000881 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000882 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000883}
884
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000885// ------------------------------ BytecodeIntrinsicNode ----------------------------------
886
887RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
888{
889 return (this->*m_emitter)(generator, dst);
890}
891
utatane.tea@gmail.combebf7852016-11-10 06:34:05 +0000892RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argument(BytecodeGenerator& generator, RegisterID* dst)
893{
894 ArgumentListNode* node = m_args->m_listNode;
895 ASSERT(node->m_expr->isNumber());
896 double value = static_cast<NumberNode*>(node->m_expr)->value();
897 int32_t index = static_cast<int32_t>(value);
898 ASSERT(value == index);
899 ASSERT(index >= 0);
900 ASSERT(!node->m_next);
901
902 // The body functions of generator and async have different mechanism for arguments.
903 ASSERT(generator.parseMode() != SourceParseMode::GeneratorBodyMode);
904 ASSERT(!isAsyncFunctionBodyParseMode(generator.parseMode()));
905
906 return generator.emitGetArgument(generator.finalDestination(dst), index);
907}
908
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +0000909RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator& generator, RegisterID* dst)
910{
911 ASSERT(!m_args->m_listNode);
912
913 return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
914}
915
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +0000916RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator& generator, RegisterID* dst)
917{
918#ifndef NDEBUG
919 ArgumentListNode* node = m_args->m_listNode;
920 RefPtr<RegisterID> condition = generator.emitNode(node);
921 generator.emitAssert(condition.get(), node->firstLine());
922 return dst;
923#else
924 UNUSED_PARAM(generator);
925 return dst;
926#endif
927}
928
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000929RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
930{
931 ArgumentListNode* node = m_args->m_listNode;
932 RefPtr<RegisterID> base = generator.emitNode(node);
933 node = node->m_next;
934 RefPtr<RegisterID> index = generator.emitNode(node);
935 node = node->m_next;
936 RefPtr<RegisterID> value = generator.emitNode(node);
937
938 ASSERT(!node->m_next);
939
940 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
941}
942
keith_miller@apple.come497e202016-06-13 21:05:36 +0000943RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator& generator, RegisterID* dst)
944{
945 ArgumentListNode* node = m_args->m_listNode;
946 RefPtr<RegisterID> function = generator.emitNode(node);
947 node = node->m_next;
948 RefPtr<RegisterID> thisRegister = generator.emitNode(node);
949 ASSERT(!node->m_next);
950
951 RefPtr<RegisterID> finalDst = generator.finalDestination(dst);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000952 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 +0000953}
954
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000955RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwTypeError(BytecodeGenerator& generator, RegisterID* dst)
956{
957 ArgumentListNode* node = m_args->m_listNode;
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000958 ASSERT(!node->m_next);
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +0000959 if (node->m_expr->isString()) {
960 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
961 generator.emitThrowTypeError(ident);
962 } else {
963 RefPtr<RegisterID> message = generator.emitNode(node);
964 generator.emitThrowStaticError(ErrorType::TypeError, message.get());
965 }
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000966 return dst;
967}
968
969RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwRangeError(BytecodeGenerator& generator, RegisterID* dst)
970{
971 ArgumentListNode* node = m_args->m_listNode;
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000972 ASSERT(!node->m_next);
utatane.tea@gmail.comb756d92b2016-10-06 17:59:33 +0000973 if (node->m_expr->isString()) {
974 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
975 generator.emitThrowRangeError(ident);
976 } else {
977 RefPtr<RegisterID> message = generator.emitNode(node);
978 generator.emitThrowStaticError(ErrorType::RangeError, message.get());
979 }
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000980
utatane.tea@gmail.com0eb0f832016-10-06 07:44:23 +0000981 return dst;
982}
983
984RegisterID* BytecodeIntrinsicNode::emit_intrinsic_throwOutOfMemoryError(BytecodeGenerator& generator, RegisterID* dst)
985{
986 ASSERT(!m_args->m_listNode);
987
988 generator.emitThrowOutOfMemoryError();
989 return dst;
990}
991
keith_miller@apple.com8844d302016-04-07 19:38:00 +0000992RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
993{
994 ArgumentListNode* node = m_args->m_listNode;
995 RefPtr<RegisterID> base = generator.emitNode(node);
996 node = node->m_next;
997
998 // Since this is a builtin we expect the creator to use a string literal as the second argument.
999 ASSERT(node->m_expr->isString());
1000 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
1001 ASSERT(!node->m_next);
1002
keith_miller@apple.come497e202016-06-13 21:05:36 +00001003 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
1004 return generator.emitTryGetById(finalDest.get(), base.get(), ident);
keith_miller@apple.com8844d302016-04-07 19:38:00 +00001005}
1006
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001007RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toNumber(BytecodeGenerator& generator, RegisterID* dst)
1008{
1009 ArgumentListNode* node = m_args->m_listNode;
1010 RefPtr<RegisterID> src = generator.emitNode(node);
1011 ASSERT(!node->m_next);
1012
1013 return generator.moveToDestinationIfNeeded(dst, generator.emitToNumber(generator.tempDestination(dst), src.get()));
1014}
1015
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +00001016RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
1017{
1018 ArgumentListNode* node = m_args->m_listNode;
1019 RefPtr<RegisterID> src = generator.emitNode(node);
1020 ASSERT(!node->m_next);
1021
1022 return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
1023}
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +00001024
1025RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isJSArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1026{
1027 ArgumentListNode* node = m_args->m_listNode;
1028 RefPtr<RegisterID> src = generator.emitNode(node);
1029 ASSERT(!node->m_next);
1030
1031 return generator.moveToDestinationIfNeeded(dst, generator.emitIsJSArray(generator.tempDestination(dst), src.get()));
1032}
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +00001033
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001034RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1035{
1036 ArgumentListNode* node = m_args->m_listNode;
1037 RefPtr<RegisterID> src = generator.emitNode(node);
1038 ASSERT(!node->m_next);
1039
1040 return generator.moveToDestinationIfNeeded(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
1041}
1042
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +00001043RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1044{
1045 ArgumentListNode* node = m_args->m_listNode;
1046 RefPtr<RegisterID> src = generator.emitNode(node);
1047 ASSERT(!node->m_next);
1048
1049 return generator.moveToDestinationIfNeeded(dst, generator.emitIsRegExpObject(generator.tempDestination(dst), src.get()));
1050}
1051
utatane.tea@gmail.com0f56f572016-02-08 23:14:47 +00001052RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
1053{
1054 ArgumentListNode* node = m_args->m_listNode;
1055 RefPtr<RegisterID> src = generator.emitNode(node);
1056 ASSERT(!node->m_next);
1057
1058 return generator.moveToDestinationIfNeeded(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
1059}
1060
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +00001061RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1062{
1063 ArgumentListNode* node = m_args->m_listNode;
1064 RefPtr<RegisterID> src = generator.emitNode(node);
1065 ASSERT(!node->m_next);
1066
1067 return generator.moveToDestinationIfNeeded(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
1068}
1069
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +00001070RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isMap(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1071{
1072 ArgumentListNode* node = m_args->m_listNode;
1073 RefPtr<RegisterID> src = generator.emitNode(node);
1074 ASSERT(!node->m_next);
1075
1076 return generator.moveToDestinationIfNeeded(dst, generator.emitIsMap(generator.tempDestination(dst), src.get()));
1077}
1078
1079RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isSet(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1080{
1081 ArgumentListNode* node = m_args->m_listNode;
1082 RefPtr<RegisterID> src = generator.emitNode(node);
1083 ASSERT(!node->m_next);
1084
1085 return generator.moveToDestinationIfNeeded(dst, generator.emitIsSet(generator.tempDestination(dst), src.get()));
1086}
1087
sbarati@apple.com3cc67a72016-08-18 17:17:41 +00001088RegisterID* BytecodeIntrinsicNode::emit_intrinsic_newArrayWithSize(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
1089{
1090 ArgumentListNode* node = m_args->m_listNode;
1091 RefPtr<RegisterID> size = generator.emitNode(node);
1092 ASSERT(!node->m_next);
1093
1094 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst);
1095 generator.emitNewArrayWithSize(finalDestination.get(), size.get());
1096 return finalDestination.get();
1097}
1098
utatane.tea@gmail.combf8978b2016-02-02 19:33:05 +00001099
1100#define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \
1101 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_##name(BytecodeGenerator& generator, RegisterID* dst) \
1102 { \
1103 ASSERT(!m_args); \
1104 ASSERT(type() == Type::Constant); \
1105 if (dst == generator.ignoredResult()) \
1106 return nullptr; \
1107 return generator.emitLoad(dst, generator.vm()->bytecodeIntrinsicRegistry().name##Value(generator)); \
1108 }
1109 JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
1110#undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
1111
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001112// ------------------------------ FunctionCallBracketNode ----------------------------------
1113
1114RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1115{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001116 bool baseIsSuper = m_base->isSuperNode();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001117 bool subscriptIsNonIndexString = isNonIndexStringElement(*m_subscript);
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001118
1119 RefPtr<RegisterID> base;
1120 if (baseIsSuper)
1121 base = emitSuperBaseForCallee(generator);
1122 else {
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001123 if (subscriptIsNonIndexString)
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001124 base = generator.emitNode(m_base);
1125 else
1126 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
1127 }
1128
1129 RefPtr<RegisterID> function;
sbarati@apple.com23315d62016-05-09 20:17:23 +00001130 RefPtr<RegisterID> thisRegister;
1131 if (baseIsSuper) {
1132 // 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.
1133 thisRegister = generator.ensureThis();
1134 }
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001135 if (subscriptIsNonIndexString) {
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001136 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001137 if (baseIsSuper)
1138 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisRegister.get(), static_cast<StringNode*>(m_subscript)->value());
1139 else
1140 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001141 } else {
1142 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
1143 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001144 if (baseIsSuper)
1145 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisRegister.get(), property.get());
1146 else
1147 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001148 }
1149
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001150 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001151 CallArguments callArguments(generator, m_args);
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001152 if (baseIsSuper) {
1153 generator.emitTDZCheck(generator.thisRegister());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001154 generator.emitMove(callArguments.thisRegister(), thisRegister.get());
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001155 } else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001156 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001157 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001158 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001159 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001160}
1161
1162// ------------------------------ FunctionCallDotNode ----------------------------------
1163
1164RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1165{
1166 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001167 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001168 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001169 bool baseIsSuper = m_base->isSuperNode();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001170 if (baseIsSuper)
1171 generator.emitMove(callArguments.thisRegister(), generator.ensureThis());
1172 else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001173 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001174 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001175 if (baseIsSuper) {
1176 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
1177 generator.emitGetById(function.get(), superBase.get(), callArguments.thisRegister(), m_ident);
1178 } else
1179 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001180 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001181 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001182 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001183}
1184
1185RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1186{
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001187 Ref<Label> realCall = generator.newLabel();
1188 Ref<Label> end = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001189 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001190 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001191 RefPtr<RegisterID> function;
oliver@apple.comba848d12014-02-12 17:14:23 +00001192 bool emitCallCheck = !generator.isBuiltinFunction();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001193 if (emitCallCheck) {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001194 if (m_base->isSuperNode()) {
1195 RefPtr<RegisterID> thisValue = generator.ensureThis();
1196 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().callPublicName());
1197 } else
1198 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +00001199 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001200 }
1201 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001202 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001203 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 +00001204 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
1205 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001206 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001207 argumentsRegister = generator.emitNode(subject);
1208 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
1209 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001210 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 +00001211 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001212 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001213 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +00001214
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001215 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1216 CallArguments callArguments(generator, m_args);
1217 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001218 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001219 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001220 } else {
1221 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1222 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +00001223 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001224 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001225 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001226 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001227 if (emitCallCheck) {
1228 generator.emitJump(end.get());
1229 generator.emitLabel(realCall.get());
1230 {
1231 CallArguments callArguments(generator, m_args);
1232 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001233 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001234 }
1235 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001236 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001237 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001238 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001239}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001240
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001241static bool areTrivialApplyArguments(ArgumentsNode* args)
1242{
1243 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
1244 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
1245}
1246
1247RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1248{
1249 // A few simple cases can be trivially handled as ordinary function calls.
1250 // function.apply(), function.apply(arg) -> identical to function.call
1251 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
1252 bool mayBeCall = areTrivialApplyArguments(m_args);
1253
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001254 Ref<Label> realCall = generator.newLabel();
1255 Ref<Label> end = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001256 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001257 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001258 RefPtr<RegisterID> function;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001259 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001260 bool emitCallCheck = !generator.isBuiltinFunction();
1261 if (emitCallCheck) {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001262 if (m_base->isSuperNode()) {
1263 RefPtr<RegisterID> thisValue = generator.ensureThis();
1264 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().applyPublicName());
1265 } else
1266 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +00001267 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
1268 }
1269 if (mayBeCall) {
1270 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
1271 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001272 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
1273 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001274 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
1275 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
1276 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1277 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1278
1279 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
1280 {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001281 Ref<Label> haveThis = generator.newLabel();
1282 Ref<Label> end = generator.newLabel();
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001283 RefPtr<RegisterID> compareResult = generator.newTemporary();
1284 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1285 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
1286 generator.emitMove(thisRegister.get(), value);
1287 generator.emitLoad(index.get(), jsNumber(1));
1288 generator.emitJump(end.get());
1289 generator.emitLabel(haveThis.get());
1290 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1291 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
1292 generator.emitMove(argumentsRegister.get(), value);
1293 generator.emitLoad(index.get(), jsNumber(2));
1294 generator.emitLabel(end.get());
1295 };
1296 generator.emitEnumeration(this, spread->expression(), extractor);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001297 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 +00001298 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +00001299 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
1300 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +00001301 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 +00001302 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1303 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +00001304 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001305 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001306 } else {
1307 m_args->m_listNode = m_args->m_listNode->m_next;
1308 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1309 CallArguments callArguments(generator, m_args);
1310 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001311 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001312 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001313 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001314 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +00001315 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001316 CallArguments callArguments(generator, m_args);
1317 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001318 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001319 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001320 } else {
1321 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
oliver@apple.comba848d12014-02-12 17:14:23 +00001322 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1323 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
1324 RefPtr<RegisterID> argsRegister;
1325 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001326 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +00001327
1328 // Function.prototype.apply ignores extra arguments, but we still
1329 // need to evaluate them for side effects.
1330 while ((args = args->m_next))
1331 generator.emitNode(args->m_expr);
1332
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001333 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 +00001334 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001335 if (emitCallCheck) {
1336 generator.emitJump(end.get());
1337 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001338 CallArguments callArguments(generator, m_args);
1339 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001340 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001341 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001342 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001343 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001344 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001345}
1346
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001347// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001348
ggaren@apple.comf3036112013-04-27 23:14:04 +00001349static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001350{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001351 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001352}
1353
1354static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1355{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001356 if (dst == srcDst)
1357 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1358 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1359 emitIncOrDec(generator, srcDst, oper);
1360 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001361}
1362
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001363RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001364{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001365 if (dst == generator.ignoredResult())
1366 return PrefixNode::emitResolve(generator, dst);
1367
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001368 ASSERT(m_expr->isResolveNode());
1369 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1370 const Identifier& ident = resolve->identifier();
1371
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001372 Variable var = generator.variable(ident);
1373 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001374 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001375 RefPtr<RegisterID> localReg = local;
1376 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001377 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001378 localReg = generator.emitMove(generator.tempDestination(dst), local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001379 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001380 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1381 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1382 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001383 }
oliver@apple.com75f804e2013-03-07 00:25:20 +00001384
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001385 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001386 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1387 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001388 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001389 if (var.isReadOnly()) {
1390 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1391 if (threwException)
1392 return value.get();
1393 }
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001394 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001395 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001396 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001397 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1398 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001399
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001400 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001401}
1402
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001403RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001404{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001405 if (dst == generator.ignoredResult())
1406 return PrefixNode::emitBracket(generator, dst);
1407
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001408 ASSERT(m_expr->isBracketAccessorNode());
1409 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1410 ExpressionNode* baseNode = bracketAccessor->base();
1411 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001412
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001413 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001414 RefPtr<RegisterID> property = generator.emitNode(subscript);
1415
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001416 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001417 RefPtr<RegisterID> value;
1418 RefPtr<RegisterID> thisValue;
1419 if (baseNode->isSuperNode()) {
1420 thisValue = generator.ensureThis();
1421 value = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
1422 } else
1423 value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001424 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001425 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001426 if (baseNode->isSuperNode())
1427 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value.get());
1428 else
1429 generator.emitPutByVal(base.get(), property.get(), value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001430 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001431 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001432}
1433
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001434RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001435{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001436 if (dst == generator.ignoredResult())
1437 return PrefixNode::emitDot(generator, dst);
1438
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001439 ASSERT(m_expr->isDotAccessorNode());
1440 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1441 ExpressionNode* baseNode = dotAccessor->base();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001442 bool baseIsSuper = baseNode->isSuperNode();
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001443 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001444
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001445 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1446
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001447 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001448 RefPtr<RegisterID> value;
1449 RefPtr<RegisterID> thisValue;
1450 if (baseIsSuper) {
1451 thisValue = generator.ensureThis();
1452 value = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), ident);
1453 } else
1454 value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001455 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001456 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001457 if (baseIsSuper)
1458 generator.emitPutById(base.get(), thisValue.get(), ident, value.get());
1459 else
1460 generator.emitPutById(base.get(), ident, value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001461 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001462 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001463}
1464
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001465RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001466{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001467 if (m_expr->isResolveNode())
1468 return emitResolve(generator, dst);
1469
1470 if (m_expr->isBracketAccessorNode())
1471 return emitBracket(generator, dst);
1472
1473 if (m_expr->isDotAccessorNode())
1474 return emitDot(generator, dst);
1475
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001476 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001477 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1478 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001479}
1480
1481// ------------------------------ DeleteResolveNode -----------------------------------
1482
1483RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1484{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001485 Variable var = generator.variable(m_ident);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001486 if (var.local()) {
1487 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001488 return generator.emitLoad(generator.finalDestination(dst), false);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001489 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001490
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001491 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001492 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001493 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
oliver@apple.com58c86752013-07-25 04:02:40 +00001494 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001495}
1496
1497// ------------------------------ DeleteBracketNode -----------------------------------
1498
1499RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1500{
1501 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001502 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001503
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001504 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001505 if (m_base->isSuperNode())
1506 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001507 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001508}
1509
1510// ------------------------------ DeleteDotNode -----------------------------------
1511
1512RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1513{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001514 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001515
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001516 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001517 if (m_base->isSuperNode())
1518 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001519 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001520}
1521
1522// ------------------------------ DeleteValueNode -----------------------------------
1523
1524RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1525{
1526 generator.emitNode(generator.ignoredResult(), m_expr);
1527
1528 // delete on a non-location expression ignores the value and returns true
1529 return generator.emitLoad(generator.finalDestination(dst), true);
1530}
1531
1532// ------------------------------ VoidNode -------------------------------------
1533
1534RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1535{
1536 if (dst == generator.ignoredResult()) {
1537 generator.emitNode(generator.ignoredResult(), m_expr);
1538 return 0;
1539 }
1540 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1541 return generator.emitLoad(dst, jsUndefined());
1542}
1543
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001544// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001545
1546RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1547{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001548 Variable var = generator.variable(m_ident);
1549 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001550 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001551 if (dst == generator.ignoredResult())
1552 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001553 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001554 }
1555
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001556 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1557 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001558 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001559 if (dst == generator.ignoredResult())
1560 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001561 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001562}
1563
1564// ------------------------------ TypeOfValueNode -----------------------------------
1565
1566RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1567{
1568 if (dst == generator.ignoredResult()) {
1569 generator.emitNode(generator.ignoredResult(), m_expr);
1570 return 0;
1571 }
1572 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1573 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1574}
1575
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001576// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001577
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001578RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001579{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001580 ASSERT(m_expr->isResolveNode());
1581 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1582 const Identifier& ident = resolve->identifier();
1583
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001584 Variable var = generator.variable(ident);
1585 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001586 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001587 RefPtr<RegisterID> localReg = local;
1588 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001589 generator.emitReadOnlyExceptionIfNeeded(var);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001590 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001591 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001592 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001593 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001594 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001595 generator.emitMove(localReg.get(), tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001596 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001597 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1598 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001599 emitIncOrDec(generator, localReg.get(), m_operator);
1600 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001601 }
1602
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001603 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001604 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1605 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001606 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001607 if (var.isReadOnly()) {
1608 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1609 if (threwException)
1610 return value.get();
1611 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001612
oliver@apple.com58c86752013-07-25 04:02:40 +00001613 emitIncOrDec(generator, value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001614 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001615 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001616 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1617 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001618 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001619}
1620
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001621RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001622{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001623 ASSERT(m_expr->isBracketAccessorNode());
1624 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1625 ExpressionNode* baseNode = bracketAccessor->base();
1626 ExpressionNode* subscript = bracketAccessor->subscript();
1627
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001628 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001629 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001630 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1631
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001632 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001633 RegisterID* value;
1634 RefPtr<RegisterID> thisValue;
1635 if (baseNode->isSuperNode()) {
1636 thisValue = generator.ensureThis();
1637 value = generator.emitGetByVal(propDst.get(), base.get(), thisValue.get(), property.get());
1638 } else
1639 value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001640 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001641 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001642 if (baseNode->isSuperNode())
1643 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
1644 else
1645 generator.emitPutByVal(base.get(), property.get(), value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001646 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001647 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1648}
1649
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001650RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001651{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001652 ASSERT(m_expr->isDotAccessorNode());
1653 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1654 ExpressionNode* baseNode = dotAccessor->base();
1655 const Identifier& ident = dotAccessor->identifier();
1656
1657 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001658 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1659
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001660 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001661 RegisterID* value;
1662 RefPtr<RegisterID> thisValue;
1663 if (baseNode->isSuperNode()) {
1664 thisValue = generator.ensureThis();
1665 value = generator.emitGetById(propDst.get(), base.get(), thisValue.get(), ident);
1666 } else
1667 value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001668 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001669 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001670 if (baseNode->isSuperNode())
1671 generator.emitPutById(base.get(), thisValue.get(), ident, value);
1672 else
1673 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001674 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001675 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1676}
1677
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001678RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001679{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001680 if (m_expr->isResolveNode())
1681 return emitResolve(generator, dst);
1682
1683 if (m_expr->isBracketAccessorNode())
1684 return emitBracket(generator, dst);
1685
1686 if (m_expr->isDotAccessorNode())
1687 return emitDot(generator, dst);
1688
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001689 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001690 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1691 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001692}
1693
1694// ------------------------------ Unary Operation Nodes -----------------------------------
1695
1696RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1697{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001698 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001699 generator.emitExpressionInfo(position(), position(), position());
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00001700 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001701}
1702
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001703// ------------------------------ UnaryPlusNode -----------------------------------
1704
1705RegisterID* UnaryPlusNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1706{
1707 ASSERT(opcodeID() == op_to_number);
1708 RefPtr<RegisterID> src = generator.emitNode(expr());
1709 generator.emitExpressionInfo(position(), position(), position());
1710 return generator.emitToNumber(generator.finalDestination(dst), src.get());
1711}
1712
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001713// ------------------------------ BitwiseNotNode -----------------------------------
1714
1715RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1716{
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00001717 RefPtr<RegisterID> src2 = generator.emitLoad(nullptr, jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001718 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1719 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 +00001720}
1721
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001722// ------------------------------ LogicalNotNode -----------------------------------
1723
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001724void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001725{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00001726 if (UNLIKELY(needsDebugHook()))
1727 generator.emitDebugHook(this);
1728
1729 // Reverse the true and false targets.
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001730 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001731}
1732
1733
1734// ------------------------------ Binary Operation Nodes -----------------------------------
1735
1736// BinaryOpNode::emitStrcat:
1737//
1738// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1739// more values, where we can determine a set of separate op_add operations would be operating on
1740// string values.
1741//
1742// This function expects to be operating on a graph of AST nodes looking something like this:
1743//
1744// (a)... (b)
1745// \ /
1746// (+) (c)
1747// \ /
1748// [d] ((+))
1749// \ /
1750// [+=]
1751//
1752// The assignment operation is optional, if it exists the register holding the value on the
1753// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1754//
1755// The method should be called on the node at the root of the tree of regular binary add
1756// operations (marked in the diagram with a double set of parentheses). This node must
1757// be performing a string concatenation (determined by statically detecting that at least
1758// one child must be a string).
1759//
1760// Since the minimum number of values being concatenated together is expected to be 3, if
1761// a lhs to a concatenating assignment is not provided then the root add should have at
1762// least one left child that is also an add that can be determined to be operating on strings.
1763//
1764RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1765{
1766 ASSERT(isAdd());
1767 ASSERT(resultDescriptor().definitelyIsString());
1768
1769 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1770 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1771 // added first, and the leftmost child is never added, so the vector produced for the
1772 // example above will be [ c, b ].
1773 Vector<ExpressionNode*, 16> reverseExpressionList;
1774 reverseExpressionList.append(m_expr2);
1775
1776 // Examine the left child of the add. So long as this is a string add, add its right-child
1777 // to the list, and keep processing along the left fork.
1778 ExpressionNode* leftMostAddChild = m_expr1;
1779 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1780 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1781 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1782 }
1783
1784 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1785
1786 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1787 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1788 // op_strcat node handle its conversion if required).
1789 if (lhs)
1790 temporaryRegisters.append(generator.newTemporary());
1791
1792 // Emit code for the leftmost node ((a) in the example).
1793 temporaryRegisters.append(generator.newTemporary());
1794 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1795 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1796
1797 // Note on ordering of conversions:
1798 //
1799 // We maintain the same ordering of conversions as we would see if the concatenations
1800 // was performed as a sequence of adds (otherwise this optimization could change
1801 // behaviour should an object have been provided a valueOf or toString method).
1802 //
1803 // Considering the above example, the sequnce of execution is:
1804 // * evaluate operand (a)
1805 // * evaluate operand (b)
1806 // * convert (a) to primitive <- (this would be triggered by the first add)
1807 // * convert (b) to primitive <- (ditto)
1808 // * evaluate operand (c)
1809 // * convert (c) to primitive <- (this would be triggered by the second add)
1810 // And optionally, if there is an assignment:
1811 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1812 //
1813 // As such we do not plant an op to convert the leftmost child now. Instead, use
1814 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1815 // once the second node has been generated. However, if the leftmost child is an
1816 // immediate we can trivially determine that no conversion will be required.
1817 // If this is the case
1818 if (leftMostAddChild->isString())
1819 leftMostAddChildTempRegister = 0;
1820
1821 while (reverseExpressionList.size()) {
1822 ExpressionNode* node = reverseExpressionList.last();
1823 reverseExpressionList.removeLast();
1824
1825 // Emit the code for the current node.
1826 temporaryRegisters.append(generator.newTemporary());
1827 generator.emitNode(temporaryRegisters.last().get(), node);
1828
1829 // On the first iteration of this loop, when we first reach this point we have just
1830 // generated the second node, which means it is time to convert the leftmost operand.
1831 if (leftMostAddChildTempRegister) {
1832 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1833 leftMostAddChildTempRegister = 0; // Only do this once.
1834 }
1835 // Plant a conversion for this node, if necessary.
1836 if (!node->isString())
1837 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1838 }
1839 ASSERT(temporaryRegisters.size() >= 3);
1840
1841 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1842 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1843 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001844 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001845 // If there is an assignment convert the lhs now. This will also copy lhs to
1846 // the temporary register we allocated for it.
1847 if (lhs)
1848 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1849
1850 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1851}
1852
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00001853void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001854{
1855 TriState branchCondition;
1856 ExpressionNode* branchExpression;
1857 tryFoldToBranch(generator, branchCondition, branchExpression);
1858
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00001859 if (UNLIKELY(needsDebugHook())) {
1860 if (branchCondition != MixedTriState)
1861 generator.emitDebugHook(this);
1862 }
1863
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001864 if (branchCondition == MixedTriState)
1865 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1866 else if (branchCondition == TrueTriState)
1867 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1868 else
1869 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1870}
1871
1872static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1873{
1874 ResultType expressionType = branchExpression->resultDescriptor();
1875
1876 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1877 return true;
1878 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1879 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1880 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1881 return true;
1882
1883 return false;
1884}
1885
1886void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1887{
1888 branchCondition = MixedTriState;
1889 branchExpression = 0;
1890
1891 ConstantNode* constant = 0;
1892 if (m_expr1->isConstant()) {
1893 constant = static_cast<ConstantNode*>(m_expr1);
1894 branchExpression = m_expr2;
1895 } else if (m_expr2->isConstant()) {
1896 constant = static_cast<ConstantNode*>(m_expr2);
1897 branchExpression = m_expr1;
1898 }
1899
1900 if (!constant)
1901 return;
1902 ASSERT(branchExpression);
1903
1904 OpcodeID opcodeID = this->opcodeID();
1905 JSValue value = constant->jsValue(generator);
1906 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1907 if (!canFoldToBranch)
1908 return;
1909
1910 if (opcodeID == op_eq || opcodeID == op_stricteq)
1911 branchCondition = triState(value.pureToBoolean());
1912 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1913 branchCondition = triState(!value.pureToBoolean());
1914}
1915
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001916RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1917{
1918 OpcodeID opcodeID = this->opcodeID();
1919
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001920 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001921 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001922 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001923 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001924
1925 if (opcodeID == op_neq) {
1926 if (m_expr1->isNull() || m_expr2->isNull()) {
1927 RefPtr<RegisterID> src = generator.tempDestination(dst);
1928 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1929 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1930 }
1931 }
1932
oliver@apple.comece74042012-12-01 00:50:39 +00001933 ExpressionNode* left = m_expr1;
1934 ExpressionNode* right = m_expr2;
1935 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1936 if (left->isString())
1937 std::swap(left, right);
1938 }
1939
1940 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001941 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001942 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001943 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001944 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001945 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1946 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001947 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001948 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001949 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001950 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001951 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001952 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1953 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001954 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 +00001955 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1956 return generator.emitUnaryOp(op_unsigned, result, result);
1957 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001958}
1959
1960RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1961{
1962 if (m_expr1->isNull() || m_expr2->isNull()) {
1963 RefPtr<RegisterID> src = generator.tempDestination(dst);
1964 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1965 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1966 }
1967
oliver@apple.comece74042012-12-01 00:50:39 +00001968 ExpressionNode* left = m_expr1;
1969 ExpressionNode* right = m_expr2;
1970 if (left->isString())
1971 std::swap(left, right);
1972
1973 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001974 RefPtr<RegisterID> src2 = generator.emitNode(right);
1975 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001976}
1977
1978RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1979{
oliver@apple.comece74042012-12-01 00:50:39 +00001980 ExpressionNode* left = m_expr1;
1981 ExpressionNode* right = m_expr2;
1982 if (left->isString())
1983 std::swap(left, right);
1984
1985 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001986 RefPtr<RegisterID> src2 = generator.emitNode(right);
1987 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001988}
1989
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001990RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1991{
1992 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001993 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001994 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001995 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 +00001996}
1997
1998RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1999{
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002000 RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
2001 RefPtr<RegisterID> isObject = generator.newTemporary();
2002 RefPtr<RegisterID> isCustom = generator.newTemporary();
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00002003 RefPtr<RegisterID> prototype = generator.newTemporary();
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002004 RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2005 RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
2006 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002007 Ref<Label> custom = generator.newLabel();
2008 Ref<Label> done = generator.newLabel();
2009 Ref<Label> typeError = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002010
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002011 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002012 generator.emitIsObject(isObject.get(), constructor.get());
2013 generator.emitJumpIfFalse(isObject.get(), typeError.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00002014
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002015 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002016 generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002017
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002018 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00002019 generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
2020
2021 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2022 generator.emitJumpIfTrue(isCustom.get(), custom.get());
2023
2024 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2025 generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
2026
2027 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2028 generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
2029
2030 generator.emitJump(done.get());
2031
2032 generator.emitLabel(typeError.get());
2033 generator.emitThrowTypeError("Right hand side of instanceof is not an object");
2034
2035 generator.emitLabel(custom.get());
2036
2037 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2038 generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
2039
2040 generator.emitLabel(done.get());
2041
2042 return dstReg.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002043}
2044
keith_miller@apple.com6fc2fb72017-02-09 00:02:20 +00002045// ------------------------------ InNode ----------------------------
2046
2047RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2048{
2049 RefPtr<RegisterID> key = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
2050 RefPtr<RegisterID> base = generator.emitNode(m_expr2);
2051 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2052 return generator.emitIn(generator.finalDestination(dst, key.get()), key.get(), base.get());
2053}
2054
2055
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002056// ------------------------------ LogicalOpNode ----------------------------
2057
2058RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2059{
2060 RefPtr<RegisterID> temp = generator.tempDestination(dst);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002061 Ref<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002062
2063 generator.emitNode(temp.get(), m_expr1);
2064 if (m_operator == OpLogicalAnd)
2065 generator.emitJumpIfFalse(temp.get(), target.get());
2066 else
2067 generator.emitJumpIfTrue(temp.get(), target.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002068 generator.emitNodeInTailPosition(temp.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002069 generator.emitLabel(target.get());
2070
2071 return generator.moveToDestinationIfNeeded(dst, temp.get());
2072}
2073
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002074void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label& trueTarget, Label& falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002075{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002076 if (UNLIKELY(needsDebugHook()))
2077 generator.emitDebugHook(this);
2078
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002079 Ref<Label> afterExpr1 = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002080 if (m_operator == OpLogicalAnd)
2081 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
2082 else
2083 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
2084 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002085
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002086 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002087}
2088
2089// ------------------------------ ConditionalNode ------------------------------
2090
2091RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2092{
2093 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002094 Ref<Label> beforeElse = generator.newLabel();
2095 Ref<Label> afterElse = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002096
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002097 Ref<Label> beforeThen = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002098 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
2099 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002100
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002101 generator.emitProfileControlFlow(m_expr1->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002102 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002103 generator.emitJump(afterElse.get());
2104
2105 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002106 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002107 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002108
2109 generator.emitLabel(afterElse.get());
2110
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002111 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002112
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002113 return newDst.get();
2114}
2115
2116// ------------------------------ ReadModifyResolveNode -----------------------------------
2117
2118// FIXME: should this be moved to be a method on BytecodeGenerator?
2119static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
2120{
2121 OpcodeID opcodeID;
2122 switch (oper) {
2123 case OpMultEq:
2124 opcodeID = op_mul;
2125 break;
2126 case OpDivEq:
2127 opcodeID = op_div;
2128 break;
2129 case OpPlusEq:
2130 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
2131 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
2132 opcodeID = op_add;
2133 break;
2134 case OpMinusEq:
2135 opcodeID = op_sub;
2136 break;
2137 case OpLShift:
2138 opcodeID = op_lshift;
2139 break;
2140 case OpRShift:
2141 opcodeID = op_rshift;
2142 break;
2143 case OpURShift:
2144 opcodeID = op_urshift;
2145 break;
2146 case OpAndEq:
2147 opcodeID = op_bitand;
2148 break;
2149 case OpXOrEq:
2150 opcodeID = op_bitxor;
2151 break;
2152 case OpOrEq:
2153 opcodeID = op_bitor;
2154 break;
2155 case OpModEq:
2156 opcodeID = op_mod;
2157 break;
utatane.tea@gmail.come9906382016-07-21 07:33:28 +00002158 case OpPowEq:
2159 opcodeID = op_pow;
2160 break;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002161 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00002162 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002163 return dst;
2164 }
2165
2166 RegisterID* src2 = generator.emitNode(m_right);
2167
2168 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2169 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2170 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002171 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00002172 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
2173 if (oper == OpURShift)
2174 return generator.emitUnaryOp(op_unsigned, result, result);
2175 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002176}
2177
2178RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2179{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002180 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002181 Variable var = generator.variable(m_ident);
2182 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002183 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002184 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002185 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002186 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2187 generator.emitProfileType(result, divotStart(), divotEnd());
2188 return result;
ggaren@apple.com6e309822012-09-05 21:44:43 +00002189 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002190
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002191 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002192 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002193 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002194 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002195 generator.emitMove(local, result.get());
2196 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002197 generator.emitProfileType(local, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002198 return generator.moveToDestinationIfNeeded(dst, result.get());
2199 }
2200
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002201 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2202 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002203 generator.emitProfileType(result, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002204 return generator.moveToDestinationIfNeeded(dst, result);
2205 }
2206
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002207 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002208 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2209 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002210 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002211 if (var.isReadOnly()) {
2212 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2213 if (threwException)
2214 return value.get();
2215 }
oliver@apple.com58c86752013-07-25 04:02:40 +00002216 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 +00002217 RegisterID* returnResult = result.get();
2218 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002219 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002220 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2221 }
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002222 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002223}
2224
sbarati@apple.come67fd782016-04-19 01:38:30 +00002225static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
2226{
2227 switch (assignmentContext) {
2228 case AssignmentContext::DeclarationStatement:
2229 return InitializationMode::Initialization;
2230 case AssignmentContext::ConstDeclarationStatement:
2231 return InitializationMode::ConstInitialization;
2232 case AssignmentContext::AssignmentExpression:
2233 return InitializationMode::NotInitialization;
2234 }
2235
2236 ASSERT_NOT_REACHED();
2237 return InitializationMode::NotInitialization;
2238}
2239
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002240// ------------------------------ AssignResolveNode -----------------------------------
2241
2242RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2243{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002244 Variable var = generator.variable(m_ident);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002245 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002246 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002247 RegisterID* result = nullptr;
2248 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2249 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002250
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002251 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002252 result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002253 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002254 generator.emitProfileType(result, var, divotStart(), divotEnd());
2255 } else if (var.isSpecial()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002256 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
2257 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002258 generator.emitMove(local, tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002259 generator.emitProfileType(local, var, divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002260 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002261 result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
2262 } else {
2263 RegisterID* right = generator.emitNode(local, m_right);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002264 generator.emitProfileType(right, var, divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002265 generator.invalidateForInContextForLocal(local);
2266 result = generator.moveToDestinationIfNeeded(dst, right);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002267 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002268
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002269 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002270 generator.liftTDZCheckIfPossible(var);
2271 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002272 }
2273
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002274 if (generator.isStrictMode())
2275 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002276 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002277 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2278 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002279 if (dst == generator.ignoredResult())
2280 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00002281 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002282 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002283 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002284 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2285 if (threwException)
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002286 return result;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002287 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002288 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002289 RegisterID* returnResult = result.get();
2290 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002291 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002292 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2293 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002294
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002295 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002296 generator.liftTDZCheckIfPossible(var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002297 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002298}
2299
2300// ------------------------------ AssignDotNode -----------------------------------
2301
2302RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2303{
2304 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2305 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002306 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002307 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002308 RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
2309 if (m_base->isSuperNode()) {
2310 RefPtr<RegisterID> thisValue = generator.ensureThis();
2311 generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
2312 } else
2313 generator.emitPutById(base.get(), m_ident, forwardResult.get());
2314 generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
2315 return generator.moveToDestinationIfNeeded(dst, forwardResult.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002316}
2317
2318// ------------------------------ ReadModifyDotNode -----------------------------------
2319
2320RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2321{
2322 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2323
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002324 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002325 RefPtr<RegisterID> value;
2326 RefPtr<RegisterID> thisValue;
2327 if (m_base->isSuperNode()) {
2328 thisValue = generator.ensureThis();
2329 value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
2330 } else
2331 value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002332 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 +00002333
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002334 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002335 RegisterID* ret;
2336 if (m_base->isSuperNode())
2337 ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
2338 else
2339 ret = generator.emitPutById(base.get(), m_ident, updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002340 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002341 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002342}
2343
2344// ------------------------------ AssignErrorNode -----------------------------------
2345
2346RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2347{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002348 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002349}
2350
2351// ------------------------------ AssignBracketNode -----------------------------------
2352
2353RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2354{
2355 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2356 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2357 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002358 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002359
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002360 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002361 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00002362
sbarati@apple.com23315d62016-05-09 20:17:23 +00002363 if (isNonIndexStringElement(*m_subscript)) {
2364 if (m_base->isSuperNode()) {
2365 RefPtr<RegisterID> thisValue = generator.ensureThis();
2366 generator.emitPutById(base.get(), thisValue.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2367 } else
2368 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2369 } else {
2370 if (m_base->isSuperNode()) {
2371 RefPtr<RegisterID> thisValue = generator.ensureThis();
2372 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), forwardResult);
2373 } else
2374 generator.emitPutByVal(base.get(), property.get(), forwardResult);
2375 }
akling@apple.come09d0422014-11-13 19:18:43 +00002376
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002377 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00002378 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002379}
2380
2381// ------------------------------ ReadModifyBracketNode -----------------------------------
2382
2383RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2384{
2385 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2386 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2387
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002388 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002389 RefPtr<RegisterID> value;
2390 RefPtr<RegisterID> thisValue;
2391 if (m_base->isSuperNode()) {
2392 thisValue = generator.ensureThis();
2393 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisValue.get(), property.get());
2394 } else
2395 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002396 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 +00002397
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002398 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002399 if (m_base->isSuperNode())
2400 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), updatedValue);
2401 else
2402 generator.emitPutByVal(base.get(), property.get(), updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002403 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002404
2405 return updatedValue;
2406}
2407
2408// ------------------------------ CommaNode ------------------------------------
2409
2410RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2411{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002412 CommaNode* node = this;
2413 for (; node && node->next(); node = node->next())
2414 generator.emitNode(generator.ignoredResult(), node->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002415 return generator.emitNodeInTailPosition(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002416}
2417
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002418// ------------------------------ SourceElements -------------------------------
2419
2420
2421inline StatementNode* SourceElements::lastStatement() const
2422{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002423 return m_tail;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002424}
2425
2426inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2427{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002428 for (StatementNode* statement = m_head; statement; statement = statement->next())
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002429 generator.emitNodeInTailPosition(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002430}
2431
2432// ------------------------------ BlockNode ------------------------------------
2433
2434inline StatementNode* BlockNode::lastStatement() const
2435{
2436 return m_statements ? m_statements->lastStatement() : 0;
2437}
2438
ggaren@apple.comddc6f102015-03-20 20:12:10 +00002439StatementNode* BlockNode::singleStatement() const
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002440{
2441 return m_statements ? m_statements->singleStatement() : 0;
2442}
2443
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002444void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002445{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002446 if (!m_statements)
2447 return;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002448 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002449 m_statements->emitBytecode(generator, dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002450 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002451}
2452
2453// ------------------------------ EmptyStatementNode ---------------------------
2454
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002455void EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002456{
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002457 RELEASE_ASSERT(needsDebugHook());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002458}
2459
2460// ------------------------------ DebuggerStatementNode ---------------------------
2461
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002462void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002463{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002464 generator.emitDebugHook(DidReachBreakpoint, position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002465}
2466
2467// ------------------------------ ExprStatementNode ----------------------------
2468
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002469void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002470{
2471 ASSERT(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002472 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002473}
2474
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002475// ------------------------------ DeclarationStatement ----------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002476
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002477void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002478{
2479 ASSERT(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002480 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002481}
2482
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002483// ------------------------------ EmptyVarExpression ----------------------------
2484
2485RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2486{
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002487 // 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 +00002488 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002489 return nullptr;
2490
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002491 Variable var = generator.variable(m_ident);
2492 if (RegisterID* local = var.local())
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002493 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002494 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002495 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2496 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002497 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002498 }
2499
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002500 return nullptr;
2501}
2502
2503// ------------------------------ EmptyLetExpression ----------------------------
2504
2505RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2506{
2507 // Lexical declarations like 'let' must move undefined into their variables so we don't
2508 // get TDZ errors for situations like this: `let x; x;`
2509 Variable var = generator.variable(m_ident);
2510 if (RegisterID* local = var.local()) {
2511 generator.emitLoad(local, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002512 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002513 } else {
2514 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2515 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002516 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002517 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002518 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002519
sbarati@apple.coma5cf2f12016-03-29 22:11:24 +00002520 generator.liftTDZCheckIfPossible(var);
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.org200ce5b2014-08-18 19:11:41 +00002523 return nullptr;
2524}
2525
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002526// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002527
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002528static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002529{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002530 if (statementNode->isBlock())
2531 return static_cast<BlockNode*>(statementNode)->singleStatement();
2532 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002533}
2534
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002535bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2536 Label*& trueTarget, FallThroughMode& fallThroughMode)
2537{
2538 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2539 if (!singleStatement)
2540 return false;
2541
2542 if (singleStatement->isBreak()) {
2543 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2544 Label* target = breakNode->trivialTarget(generator);
2545 if (!target)
2546 return false;
2547 trueTarget = target;
2548 fallThroughMode = FallThroughMeansFalse;
2549 return true;
2550 }
2551
2552 if (singleStatement->isContinue()) {
2553 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2554 Label* target = continueNode->trivialTarget(generator);
2555 if (!target)
2556 return false;
2557 trueTarget = target;
2558 fallThroughMode = FallThroughMeansFalse;
2559 return true;
2560 }
2561
2562 return false;
2563}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002564
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002565void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002566{
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002567 Ref<Label> beforeThen = generator.newLabel();
2568 Ref<Label> beforeElse = generator.newLabel();
2569 Ref<Label> afterElse = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002570
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002571 Label* trueTarget = beforeThen.ptr();
2572 Label& falseTarget = beforeElse.get();
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002573 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2574 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2575
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002576 generator.emitNodeInConditionContext(m_condition, *trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002577 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002578 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002579
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002580 if (!didFoldIfBlock) {
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002581 generator.emitNodeInTailPosition(dst, m_ifBlock);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002582 if (m_elseBlock)
2583 generator.emitJump(afterElse.get());
2584 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002585
2586 generator.emitLabel(beforeElse.get());
2587
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002588 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002589 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002590 generator.emitNodeInTailPosition(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002591 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002592
2593 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002594 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2595 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002596}
2597
2598// ------------------------------ DoWhileNode ----------------------------------
2599
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002600void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002601{
oliver@apple.com6a976452013-03-11 21:02:39 +00002602 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002603
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002604 Ref<Label> topOfLoop = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002605 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002606 generator.emitLoopHint();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002607
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002608 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002609
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002610 generator.emitLabel(*scope->continueTarget());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002611 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002612
2613 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002614}
2615
2616// ------------------------------ WhileNode ------------------------------------
2617
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002618void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002619{
oliver@apple.com6a976452013-03-11 21:02:39 +00002620 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002621 Ref<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002622
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002623 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002624
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002625 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002626 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002627
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002628 generator.emitProfileControlFlow(m_statement->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002629 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002630
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002631 generator.emitLabel(*scope->continueTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002632
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002633 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002634
2635 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002636
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002637 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002638}
2639
2640// ------------------------------ ForNode --------------------------------------
2641
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002642void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002643{
oliver@apple.com6a976452013-03-11 21:02:39 +00002644 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002645
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002646 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002647 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002648
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002649 if (m_expr1)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002650 generator.emitNode(generator.ignoredResult(), m_expr1);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002651
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002652 Ref<Label> topOfLoop = generator.newLabel();
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002653 if (m_expr2)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002654 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002655
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002656 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002657 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002658 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002659
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002660 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002661
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002662 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002663 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002664 if (m_expr3)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002665 generator.emitNode(generator.ignoredResult(), m_expr3);
2666
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002667 if (m_expr2)
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002668 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002669 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002670 generator.emitJump(topOfLoop.get());
2671
2672 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002673 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002674 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002675}
2676
2677// ------------------------------ ForInNode ------------------------------------
2678
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002679RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002680{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002681 if (m_lexpr->isResolveNode()) {
2682 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002683 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002684 }
2685
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002686 if (m_lexpr->isDestructuringNode()) {
2687 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002688 auto binding = assignNode->bindings();
2689 if (!binding->isBindingNode())
2690 return nullptr;
2691
2692 auto simpleBinding = static_cast<BindingNode*>(binding);
2693 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002694 Variable var = generator.variable(ident);
2695 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002696 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002697 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002698 }
2699
2700 return nullptr;
2701}
2702
2703void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2704{
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002705 auto lambdaEmitResolveVariable = [&](const Identifier& ident)
2706 {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002707 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002708 if (RegisterID* local = var.local()) {
2709 if (var.isReadOnly())
2710 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002711 generator.emitMove(local, propertyName);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002712 } else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002713 if (generator.isStrictMode())
2714 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002715 if (var.isReadOnly())
2716 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002717 RegisterID* scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002718 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002719 generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002720 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002721 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002722 };
2723
2724 if (m_lexpr->isResolveNode()) {
2725 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2726 lambdaEmitResolveVariable(ident);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002727 return;
2728 }
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002729
2730 if (m_lexpr->isAssignResolveNode()) {
2731 const Identifier& ident = static_cast<AssignResolveNode*>(m_lexpr)->identifier();
2732 lambdaEmitResolveVariable(ident);
2733 return;
2734 }
2735
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002736 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002737 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2738 const Identifier& ident = assignNode->identifier();
sbarati@apple.com23315d62016-05-09 20:17:23 +00002739 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002740 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002741 if (assignNode->base()->isSuperNode()) {
2742 RefPtr<RegisterID> thisValue = generator.ensureThis();
2743 generator.emitPutById(base.get(), thisValue.get(), ident, propertyName);
2744 } else
2745 generator.emitPutById(base.get(), ident, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002746 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002747 return;
2748 }
2749 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002750 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002751 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002752 RefPtr<RegisterID> subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002753 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002754 if (assignNode->base()->isSuperNode()) {
2755 RefPtr<RegisterID> thisValue = generator.ensureThis();
2756 generator.emitPutByVal(base.get(), thisValue.get(), subscript.get(), propertyName);
2757 } else
2758 generator.emitPutByVal(base.get(), subscript.get(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002759 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002760 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002761 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002762
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002763 if (m_lexpr->isDestructuringNode()) {
2764 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002765 auto binding = assignNode->bindings();
2766 if (!binding->isBindingNode()) {
2767 assignNode->bindings()->bindValue(generator, propertyName);
2768 return;
2769 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002770
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002771 auto simpleBinding = static_cast<BindingNode*>(binding);
2772 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002773 Variable var = generator.variable(ident);
2774 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002775 assignNode->bindings()->bindValue(generator, propertyName);
2776 return;
2777 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002778 generator.emitMove(var.local(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002779 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002780 return;
2781 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002782
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002783 RELEASE_ASSERT_NOT_REACHED();
2784}
2785
commit-queue@webkit.org3057eed2016-09-21 22:52:37 +00002786void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002787{
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002788 if (!m_lexpr->isAssignResolveNode() && !m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002789 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002790 return;
2791 }
2792
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002793 Ref<Label> end = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002794
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002795 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002796 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002797
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002798 if (m_lexpr->isAssignResolveNode())
2799 generator.emitNode(generator.ignoredResult(), m_lexpr);
2800
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002801 RefPtr<RegisterID> base = generator.newTemporary();
2802 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002803 RefPtr<RegisterID> enumerator;
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002804
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002805 generator.emitNode(base.get(), m_expr);
2806 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002807 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002808
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002809 // Pause at the assignment expression for each for..in iteration.
2810 generator.emitDebugHook(m_lexpr);
2811
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002812 int profilerStartOffset = m_statement->startOffset();
2813 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002814
2815 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2816
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002817 // Indexed property loop.
2818 {
2819 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002820 Ref<Label> loopStart = generator.newLabel();
2821 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002822
msaboff@apple.comb644c252015-03-24 10:05:21 +00002823 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002824 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2825 RefPtr<RegisterID> propertyName = generator.newTemporary();
2826
2827 generator.emitLabel(loopStart.get());
2828 generator.emitLoopHint();
2829
2830 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2831 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2832 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002833 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002834
2835 generator.emitToIndexString(propertyName.get(), i.get());
2836 this->emitLoopHeader(generator, propertyName.get());
2837
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002838 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002839
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002840 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002841 generator.emitNode(dst, m_statement);
2842 generator.popIndexedForInScope(local.get());
2843
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002844 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002845
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002846 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002847 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002848 generator.emitInc(i.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002849 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002850 generator.emitJump(loopStart.get());
2851
2852 generator.emitLabel(scope->breakTarget());
2853 generator.emitJump(end.get());
2854 generator.emitLabel(loopEnd.get());
2855 }
2856
2857 // Structure property loop.
2858 {
2859 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002860 Ref<Label> loopStart = generator.newLabel();
2861 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002862
msaboff@apple.comb644c252015-03-24 10:05:21 +00002863 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002864 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002865 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002866
2867 generator.emitLabel(loopStart.get());
2868 generator.emitLoopHint();
2869
2870 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2871 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002872 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002873 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002874
2875 this->emitLoopHeader(generator, propertyName.get());
2876
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002877 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002878
msaboff@apple.comb644c252015-03-24 10:05:21 +00002879 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002880 generator.emitNode(dst, m_statement);
2881 generator.popStructureForInScope(local.get());
2882
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002883 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002884
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002885 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002886 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002887 generator.emitInc(enumeratorIndex.get());
2888 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002889 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002890 generator.emitJump(loopStart.get());
2891
2892 generator.emitLabel(scope->breakTarget());
2893 generator.emitJump(end.get());
2894 generator.emitLabel(loopEnd.get());
2895 }
2896
2897 // Generic property loop.
2898 {
2899 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002900 Ref<Label> loopStart = generator.newLabel();
2901 Ref<Label> loopEnd = generator.newLabel();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002902
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002903 RefPtr<RegisterID> propertyName = generator.newTemporary();
2904
msaboff@apple.comb644c252015-03-24 10:05:21 +00002905 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002906
2907 generator.emitLabel(loopStart.get());
2908 generator.emitLoopHint();
2909
msaboff@apple.comb644c252015-03-24 10:05:21 +00002910 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2911 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2912
2913 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002914 generator.emitJumpIfFalse(result.get(), *scope->continueTarget());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002915
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002916 this->emitLoopHeader(generator, propertyName.get());
2917
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002918 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002919
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002920 generator.emitNode(dst, m_statement);
2921
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00002922 generator.emitLabel(*scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002923 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002924 generator.emitInc(enumeratorIndex.get());
2925 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgb5fbd452016-10-12 18:47:48 +00002926 generator.emitDebugHook(m_lexpr); // Pause at the assignment expression for each for..in iteration.
msaboff@apple.comb644c252015-03-24 10:05:21 +00002927 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002928
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002929 generator.emitLabel(scope->breakTarget());
2930 generator.emitJump(end.get());
2931 generator.emitLabel(loopEnd.get());
2932 }
2933
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002934 generator.emitLabel(end.get());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002935 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002936 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002937}
2938
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002939// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002940void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2941{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002942 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002943 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002944 return;
2945 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002946
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002947 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002948 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002949 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002950 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002951 if (m_lexpr->isResolveNode()) {
2952 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002953 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002954 if (RegisterID* local = var.local()) {
2955 if (var.isReadOnly())
2956 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002957 generator.emitMove(local, value);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002958 } else {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002959 if (generator.isStrictMode())
2960 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002961 if (var.isReadOnly())
2962 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002963 RegisterID* scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002964 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002965 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002966 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002967 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00002968 } else if (m_lexpr->isDotAccessorNode()) {
2969 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2970 const Identifier& ident = assignNode->identifier();
2971 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2972
2973 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002974 if (assignNode->base()->isSuperNode()) {
2975 RefPtr<RegisterID> thisValue = generator.ensureThis();
2976 generator.emitPutById(base.get(), thisValue.get(), ident, value);
2977 } else
2978 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002979 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002980 } else if (m_lexpr->isBracketAccessorNode()) {
2981 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
2982 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2983 RegisterID* subscript = generator.emitNode(assignNode->subscript());
2984
2985 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002986 if (assignNode->base()->isSuperNode()) {
2987 RefPtr<RegisterID> thisValue = generator.ensureThis();
2988 generator.emitPutByVal(base.get(), thisValue.get(), subscript, value);
2989 } else
2990 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002991 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002992 } else {
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002993 ASSERT(m_lexpr->isDestructuringNode());
2994 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00002995 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002996 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002997 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002998 generator.emitNode(dst, m_statement);
2999 };
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003000 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
3001 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003002 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00003003}
3004
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003005// ------------------------------ ContinueNode ---------------------------------
3006
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003007Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
3008{
3009 if (generator.shouldEmitDebugHooks())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003010 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003011
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00003012 LabelScopePtr scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003013 ASSERT(scope);
3014
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00003015 if (generator.labelScopeDepth() != scope->scopeDepth())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003016 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003017
3018 return scope->continueTarget();
3019}
3020
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003021void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003022{
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00003023 LabelScopePtr scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003024 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003025
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003026 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), *scope->continueTarget());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003027 if (!hasFinally) {
3028 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3029 generator.restoreScopeRegister(lexicalScopeIndex);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003030 generator.emitJump(*scope->continueTarget());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003031 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003032
3033 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003034}
3035
3036// ------------------------------ BreakNode ------------------------------------
3037
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003038Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
3039{
3040 if (generator.shouldEmitDebugHooks())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003041 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003042
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00003043 LabelScopePtr scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003044 ASSERT(scope);
3045
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00003046 if (generator.labelScopeDepth() != scope->scopeDepth())
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003047 return nullptr;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003048
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003049 return &scope->breakTarget();
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00003050}
3051
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003052void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003053{
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00003054 LabelScopePtr scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003055 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003056
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003057 bool hasFinally = generator.emitJumpViaFinallyIfNeeded(scope->scopeDepth(), scope->breakTarget());
3058 if (!hasFinally) {
3059 int lexicalScopeIndex = generator.labelScopeDepthToLexicalScopeIndex(scope->scopeDepth());
3060 generator.restoreScopeRegister(lexicalScopeIndex);
3061 generator.emitJump(scope->breakTarget());
3062 }
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003063
3064 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003065}
3066
3067// ------------------------------ ReturnNode -----------------------------------
3068
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003069void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003070{
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003071 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003072
3073 if (dst == generator.ignoredResult())
3074 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00003075
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003076 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003077
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003078 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003079
3080 bool hasFinally = generator.emitReturnViaFinallyIfNeeded(returnRegister.get());
3081 if (!hasFinally) {
3082 generator.emitWillLeaveCallFrameDebugHook();
3083 generator.emitReturn(returnRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003084 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00003085
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003086 generator.emitProfileControlFlow(endOffset());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003087 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
3088 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
3089 if (generator.vm()->controlFlowProfiler())
3090 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003091}
3092
3093// ------------------------------ WithNode -------------------------------------
3094
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003095void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003096{
ggaren@apple.com170d6f22012-09-02 21:27:23 +00003097 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003098 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003099 generator.emitPushWithScope(scope.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003100 generator.emitNodeInTailPosition(dst, m_statement);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003101 generator.emitPopWithScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003102}
3103
3104// ------------------------------ CaseClauseNode --------------------------------
3105
3106inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3107{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003108 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003109 if (!m_statements)
3110 return;
3111 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003112}
3113
3114// ------------------------------ CaseBlockNode --------------------------------
3115
3116enum SwitchKind {
3117 SwitchUnset = 0,
3118 SwitchNumber = 1,
3119 SwitchString = 2,
3120 SwitchNeither = 3
3121};
3122
3123static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
3124{
3125 for (; list; list = list->getNext()) {
3126 ExpressionNode* clauseExpression = list->getClause()->expr();
3127 literalVector.append(clauseExpression);
3128 if (clauseExpression->isNumber()) {
3129 double value = static_cast<NumberNode*>(clauseExpression)->value();
3130 int32_t intVal = static_cast<int32_t>(value);
3131 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
3132 typeForTable = SwitchNeither;
3133 break;
3134 }
3135 if (intVal < min_num)
3136 min_num = intVal;
3137 if (intVal > max_num)
3138 max_num = intVal;
3139 typeForTable = SwitchNumber;
3140 continue;
3141 }
3142 if (clauseExpression->isString()) {
3143 if (typeForTable & ~SwitchString) {
3144 typeForTable = SwitchNeither;
3145 break;
3146 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00003147 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00003148 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00003149 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003150 if (intVal < min_num)
3151 min_num = intVal;
3152 if (intVal > max_num)
3153 max_num = intVal;
3154 }
3155 typeForTable = SwitchString;
3156 continue;
3157 }
3158 typeForTable = SwitchNeither;
3159 break;
3160 }
3161}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003162
3163static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003164{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003165 size_t length = 0;
3166 for (ClauseListNode* node = list1; node; node = node->getNext())
3167 ++length;
3168 for (ClauseListNode* node = list2; node; node = node->getNext())
3169 ++length;
3170 return length;
3171}
3172
3173SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
3174{
3175 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
3176 return SwitchInfo::SwitchNone;
3177
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003178 SwitchKind typeForTable = SwitchUnset;
3179 bool singleCharacterSwitch = true;
3180
3181 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3182 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3183
3184 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
3185 return SwitchInfo::SwitchNone;
3186
3187 if (typeForTable == SwitchNumber) {
3188 int32_t range = max_num - min_num;
3189 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3190 return SwitchInfo::SwitchImmediate;
3191 return SwitchInfo::SwitchNone;
3192 }
3193
3194 ASSERT(typeForTable == SwitchString);
3195
3196 if (singleCharacterSwitch) {
3197 int32_t range = max_num - min_num;
3198 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3199 return SwitchInfo::SwitchCharacter;
3200 }
3201
3202 return SwitchInfo::SwitchString;
3203}
3204
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003205void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003206{
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003207 Vector<Ref<Label>, 8> labelVector;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003208 Vector<ExpressionNode*, 8> literalVector;
3209 int32_t min_num = std::numeric_limits<int32_t>::max();
3210 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003211 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003212
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003213 Ref<Label> defaultLabel = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003214 if (switchType != SwitchInfo::SwitchNone) {
3215 // Prepare the various labels
3216 for (uint32_t i = 0; i < literalVector.size(); i++)
3217 labelVector.append(generator.newLabel());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003218 generator.beginSwitch(switchExpression, switchType);
3219 } else {
3220 // Setup jumps
3221 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3222 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3223 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3224 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3225 labelVector.append(generator.newLabel());
3226 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3227 }
3228
3229 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3230 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3231 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3232 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3233 labelVector.append(generator.newLabel());
3234 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3235 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003236 generator.emitJump(defaultLabel.get());
3237 }
3238
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003239 size_t i = 0;
3240 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3241 generator.emitLabel(labelVector[i++].get());
3242 list->getClause()->emitBytecode(generator, dst);
3243 }
3244
3245 if (m_defaultClause) {
3246 generator.emitLabel(defaultLabel.get());
3247 m_defaultClause->emitBytecode(generator, dst);
3248 }
3249
3250 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3251 generator.emitLabel(labelVector[i++].get());
3252 list->getClause()->emitBytecode(generator, dst);
3253 }
3254 if (!m_defaultClause)
3255 generator.emitLabel(defaultLabel.get());
3256
3257 ASSERT(i == labelVector.size());
3258 if (switchType != SwitchInfo::SwitchNone) {
3259 ASSERT(labelVector.size() == literalVector.size());
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003260 generator.endSwitch(labelVector.size(), labelVector, literalVector.data(), defaultLabel.get(), min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003261 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003262}
3263
3264// ------------------------------ SwitchNode -----------------------------------
3265
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003266void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003267{
oliver@apple.com6a976452013-03-11 21:02:39 +00003268 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003269
3270 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003271
sbarati@apple.combdbba812015-12-19 00:19:41 +00003272 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::DoNotOptimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003273 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003274 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003275
3276 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003277 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003278}
3279
3280// ------------------------------ LabelNode ------------------------------------
3281
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003282void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003283{
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003284 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003285
oliver@apple.com6a976452013-03-11 21:02:39 +00003286 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00003287 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003288
3289 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003290}
3291
3292// ------------------------------ ThrowNode ------------------------------------
3293
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003294void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003295{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003296 if (dst == generator.ignoredResult())
3297 dst = 0;
3298 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003299 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003300 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003301
3302 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003303}
3304
3305// ------------------------------ TryNode --------------------------------------
3306
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003307void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003308{
3309 // NOTE: The catch and finally blocks must be labeled explicitly, so the
3310 // optimizer knows they may be jumped to from anywhere.
3311
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003312 ASSERT(m_catchBlock || m_finallyBlock);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003313 BytecodeGenerator::CompletionRecordScope completionRecordScope(generator, m_finallyBlock);
3314
3315 RefPtr<Label> catchLabel;
3316 RefPtr<Label> catchEndLabel;
3317 RefPtr<Label> finallyViaThrowLabel;
3318 RefPtr<Label> finallyLabel;
3319 RefPtr<Label> finallyEndLabel;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003320
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003321 Ref<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003322 generator.emitLabel(tryStartLabel.get());
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003323
3324 if (m_finallyBlock) {
3325 finallyViaThrowLabel = generator.newLabel();
3326 finallyLabel = generator.newLabel();
3327 finallyEndLabel = generator.newLabel();
3328
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003329 generator.pushFinallyControlFlowScope(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003330 }
3331 if (m_catchBlock) {
3332 catchLabel = generator.newLabel();
3333 catchEndLabel = generator.newLabel();
3334 }
3335
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003336 Label& tryHandlerLabel = m_catchBlock ? *catchLabel : *finallyViaThrowLabel;
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003337 HandlerType tryHandlerType = m_catchBlock ? HandlerType::Catch : HandlerType::Finally;
3338 TryData* tryData = generator.pushTry(tryStartLabel.get(), tryHandlerLabel, tryHandlerType);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003339
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003340 generator.emitNode(dst, m_tryBlock);
3341
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003342 if (m_finallyBlock)
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003343 generator.emitJump(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003344 else
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003345 generator.emitJump(*catchEndLabel);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003346
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003347 Ref<Label> endTryLabel = generator.newEmittedLabel();
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003348 generator.popTry(tryData, endTryLabel.get());
3349
3350 if (m_catchBlock) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003351 // Uncaught exception path: the catch block.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003352 generator.emitLabel(*catchLabel);
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003353 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003354 RegisterID* unused = generator.newTemporary();
3355 generator.emitCatch(unused, thrownValueRegister.get());
3356 generator.restoreScopeRegister();
3357
3358 TryData* tryData = nullptr;
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003359 if (m_finallyBlock) {
3360 // If the catch block throws an exception and we have a finally block, then the finally
3361 // block should "catch" that exception.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003362 tryData = generator.pushTry(*catchLabel, *finallyViaThrowLabel, HandlerType::Finally);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003363 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00003364
utatane.tea@gmail.com08fe3112016-01-22 04:21:36 +00003365 generator.emitPushCatchScope(m_lexicalVariables);
3366 m_catchPattern->bindValue(generator, thrownValueRegister.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003367 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003368 if (m_finallyBlock)
3369 generator.emitNode(dst, m_catchBlock);
3370 else
3371 generator.emitNodeInTailPosition(dst, m_catchBlock);
msaboff@apple.com78461ac2016-06-02 04:07:14 +00003372 generator.emitLoad(thrownValueRegister.get(), jsUndefined());
sbarati@apple.com62be0b02015-09-19 15:36:46 +00003373 generator.emitPopCatchScope(m_lexicalVariables);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003374
3375 if (m_finallyBlock) {
3376 generator.emitSetCompletionType(CompletionType::Normal);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003377 generator.emitJump(*finallyLabel);
3378 generator.popTry(tryData, *finallyViaThrowLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003379 }
3380
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003381 generator.emitLabel(*catchEndLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003382 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003383 }
3384
3385 if (m_finallyBlock) {
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003386 FinallyContext finallyContext = generator.popFinallyControlFlowScope();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003387
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003388 // Entry to the finally block for CompletionType::Throw.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003389 generator.emitLabel(*finallyViaThrowLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003390 RegisterID* unused = generator.newTemporary();
3391 generator.emitCatch(generator.completionValueRegister(), unused);
3392 generator.emitSetCompletionType(CompletionType::Throw);
3393
3394 // Entry to the finally block for CompletionTypes other than Throw.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003395 generator.emitLabel(*finallyLabel);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003396 generator.restoreScopeRegister();
3397
3398 RefPtr<RegisterID> savedCompletionTypeRegister = generator.newTemporary();
3399 generator.emitMove(savedCompletionTypeRegister.get(), generator.completionTypeRegister());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003400
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003401 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003402 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003403 generator.emitNodeInTailPosition(dst, m_finallyBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003404
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003405 generator.emitFinallyCompletion(finallyContext, savedCompletionTypeRegister.get(), *finallyEndLabel);
3406 generator.emitLabel(*finallyEndLabel);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003407 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mark.lam@apple.com8bdb8db2016-12-22 22:48:32 +00003408 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003409}
3410
3411// ------------------------------ ScopeNode -----------------------------
3412
3413inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
3414{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003415 if (!m_statements)
3416 return;
3417 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003418}
3419
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003420static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
3421{
3422 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
3423
3424 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3425 generator.emitLoad(dstRegister.get(), jsUndefined());
3426 generator.emitProfileControlFlow(scopeNode.startStartOffset());
3427 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
3428
3429 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
3430 generator.emitEnd(dstRegister.get());
3431}
3432
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003433// ------------------------------ ProgramNode -----------------------------
3434
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003435void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003436{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003437 emitProgramNodeBytecode(generator, *this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003438}
3439
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003440// ------------------------------ ModuleProgramNode --------------------
3441
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003442void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003443{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003444 emitProgramNodeBytecode(generator, *this);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003445}
3446
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003447// ------------------------------ EvalNode -----------------------------
3448
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003449void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003450{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003451 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003452
3453 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3454 generator.emitLoad(dstRegister.get(), jsUndefined());
3455 emitStatementsBytecode(generator, dstRegister.get());
3456
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003457 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003458 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003459}
3460
ggaren@apple.come7afe402015-08-10 20:24:35 +00003461// ------------------------------ FunctionNode -----------------------------
ggaren@apple.com6f851d72014-12-04 23:47:49 +00003462
3463void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003464{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00003465 if (generator.vm()->typeProfiler()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003466 for (size_t i = 0; i < m_parameters->size(); i++) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003467 // Destructuring parameters are handled in destructuring nodes.
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00003468 if (!m_parameters->at(i).first->isBindingNode())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003469 continue;
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00003470 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003471 RegisterID reg(CallFrame::argumentOffset(i));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003472 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003473 }
3474 }
3475
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003476 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003477 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003478
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003479 switch (generator.parseMode()) {
3480 case SourceParseMode::GeneratorWrapperFunctionMode: {
3481 StatementNode* singleStatement = this->singleStatement();
3482 ASSERT(singleStatement->isExprStatement());
3483 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3484 ExpressionNode* expr = exprStatement->expr();
3485 ASSERT(expr->isFuncExprNode());
3486 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003487
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003488 RefPtr<RegisterID> next = generator.newTemporary();
3489 generator.emitNode(next.get(), funcExpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003490
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003491 if (generator.superBinding() == SuperBinding::Needed) {
3492 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3493 emitPutHomeObject(generator, next.get(), homeObject.get());
3494 }
3495
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003496 generator.emitPutGeneratorFields(next.get());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003497
mark.lam@apple.comfa35e782013-11-19 21:55:16 +00003498 ASSERT(startOffset() >= lineStartOffset());
3499 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003500 generator.emitReturn(generator.generatorRegister());
3501 break;
3502 }
3503
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003504 case SourceParseMode::AsyncFunctionMode:
3505 case SourceParseMode::AsyncMethodMode:
3506 case SourceParseMode::AsyncArrowFunctionMode: {
3507 StatementNode* singleStatement = this->singleStatement();
3508 ASSERT(singleStatement->isExprStatement());
3509 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3510 ExpressionNode* expr = exprStatement->expr();
3511 ASSERT(expr->isFuncExprNode());
3512 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
3513
3514 RefPtr<RegisterID> next = generator.newTemporary();
3515 generator.emitNode(next.get(), funcExpr);
3516
gskachkov@gmail.comc78531a2017-01-10 21:13:33 +00003517 if (generator.superBinding() == SuperBinding::Needed || (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isSuperUsedInInnerArrowFunction())) {
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003518 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3519 emitPutHomeObject(generator, next.get(), homeObject.get());
3520 }
gskachkov@gmail.com48a2a9a2017-01-19 17:10:31 +00003521
3522 if (generator.parseMode() == SourceParseMode::AsyncArrowFunctionMode && generator.isThisUsedInInnerArrowFunction())
3523 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003524
3525 generator.emitPutGeneratorFields(next.get());
3526
3527 ASSERT(startOffset() >= lineStartOffset());
3528 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3529
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003530 // load and call @asyncFunctionResume
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003531 auto var = generator.variable(generator.propertyNames().builtinNames().asyncFunctionResumePrivateName());
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003532 RefPtr<RegisterID> scope = generator.newTemporary();
3533 generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003534 RefPtr<RegisterID> asyncFunctionResume = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003535
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003536 CallArguments args(generator, nullptr, 4);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003537 unsigned argumentCount = 0;
3538 generator.emitLoad(args.thisRegister(), jsUndefined());
3539 generator.emitMove(args.argumentRegister(argumentCount++), generator.generatorRegister());
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003540 generator.emitMove(args.argumentRegister(argumentCount++), generator.promiseCapabilityRegister());
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003541 generator.emitLoad(args.argumentRegister(argumentCount++), jsUndefined());
3542 generator.emitLoad(args.argumentRegister(argumentCount++), jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
3543 // JSTextPosition(int _line, int _offset, int _lineStartOffset)
3544 JSTextPosition divot(firstLine(), startOffset(), lineStartOffset());
3545
3546 RefPtr<RegisterID> result = generator.newTemporary();
caitp@igalia.com5f1b4ea2016-11-15 04:28:45 +00003547 generator.emitCallInTailPosition(result.get(), asyncFunctionResume.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No);
caitp@igalia.com04d4f602016-10-28 16:37:38 +00003548 generator.emitReturn(result.get());
3549 break;
3550 }
3551
3552 case SourceParseMode::AsyncArrowFunctionBodyMode:
3553 case SourceParseMode::AsyncFunctionBodyMode:
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003554 case SourceParseMode::GeneratorBodyMode: {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003555 Ref<Label> generatorBodyLabel = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003556 {
3557 RefPtr<RegisterID> condition = generator.newTemporary();
3558 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))));
3559 generator.emitJumpIfTrue(condition.get(), generatorBodyLabel.get());
3560
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003561 Ref<Label> throwLabel = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003562 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))));
3563 generator.emitJumpIfTrue(condition.get(), throwLabel.get());
3564
3565 generator.emitReturn(generator.generatorValueRegister());
3566
3567 generator.emitLabel(throwLabel.get());
3568 generator.emitThrow(generator.generatorValueRegister());
3569 }
3570
3571 generator.emitLabel(generatorBodyLabel.get());
3572
3573 emitStatementsBytecode(generator, generator.ignoredResult());
3574
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003575 Ref<Label> done = generator.newLabel();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003576 generator.emitLabel(done.get());
3577 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003578 break;
3579 }
3580
3581 default: {
3582 emitStatementsBytecode(generator, generator.ignoredResult());
3583
3584 StatementNode* singleStatement = this->singleStatement();
3585 ReturnNode* returnNode = 0;
3586
3587 // Check for a return statement at the end of a function composed of a single block.
3588 if (singleStatement && singleStatement->isBlock()) {
3589 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
3590 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
3591 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
3592 }
3593
3594 // If there is no return we must automatically insert one.
3595 if (!returnNode) {
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003596 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isSuperCallUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +00003597 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
3598
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003599 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
3600 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
3601 ASSERT(startOffset() >= lineStartOffset());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003602 generator.emitWillLeaveCallFrameDebugHook();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003603 generator.emitReturn(r0);
3604 return;
3605 }
3606 break;
3607 }
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003608 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003609}
3610
3611// ------------------------------ FuncDeclNode ---------------------------------
3612
sbarati@apple.come86176c2016-04-07 21:01:42 +00003613void FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003614{
sbarati@apple.come86176c2016-04-07 21:01:42 +00003615 generator.hoistSloppyModeFunctionIfNecessary(metadata()->ident());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003616}
3617
3618// ------------------------------ FuncExprNode ---------------------------------
3619
3620RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3621{
3622 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3623}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003624
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00003625// ------------------------------ ArrowFuncExprNode ---------------------------------
3626
3627RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3628{
3629 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3630}
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003631
mark.lam@apple.com43137872016-03-17 14:58:57 +00003632// ------------------------------ MethodDefinitionNode ---------------------------------
3633
3634RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3635{
3636 return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
3637}
3638
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003639// ------------------------------ YieldExprNode --------------------------------
3640
3641RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3642{
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003643 if (!delegate()) {
3644 RefPtr<RegisterID> arg = nullptr;
3645 if (argument()) {
3646 arg = generator.newTemporary();
3647 generator.emitNode(arg.get(), argument());
3648 } else
3649 arg = generator.emitLoad(nullptr, jsUndefined());
3650 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3651 if (dst == generator.ignoredResult())
3652 return nullptr;
3653 return generator.emitMove(generator.finalDestination(dst), value.get());
3654 }
3655 RefPtr<RegisterID> arg = generator.newTemporary();
3656 generator.emitNode(arg.get(), argument());
3657 RefPtr<RegisterID> value = generator.emitDelegateYield(arg.get(), this);
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003658 if (dst == generator.ignoredResult())
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003659 return nullptr;
3660 return generator.emitMove(generator.finalDestination(dst), value.get());
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003661}
3662
caitp@igalia.com0096c962016-09-23 22:24:27 +00003663// ------------------------------ AwaitExprNode --------------------------------
3664
3665RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3666{
3667 RefPtr<RegisterID> arg = generator.newTemporary();
3668 generator.emitNode(arg.get(), argument());
3669 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3670 if (dst == generator.ignoredResult())
3671 return nullptr;
3672 return generator.emitMove(generator.finalDestination(dst), value.get());
3673}
3674
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003675// ------------------------------ ClassDeclNode ---------------------------------
3676
3677void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3678{
3679 generator.emitNode(dst, m_classDeclaration);
3680}
3681
3682// ------------------------------ ClassExprNode ---------------------------------
3683
3684RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3685{
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003686 if (!m_name.isNull())
sbarati@apple.combdbba812015-12-19 00:19:41 +00003687 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003688
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003689 RefPtr<RegisterID> superclass;
3690 if (m_classHeritage) {
3691 superclass = generator.newTemporary();
3692 generator.emitNode(superclass.get(), m_classHeritage);
3693 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003694
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003695 RefPtr<RegisterID> constructor;
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003696 bool needsHomeObject = false;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003697
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003698 // FIXME: Make the prototype non-configurable & non-writable.
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003699 if (m_constructorExpression) {
3700 ASSERT(m_constructorExpression->isFuncExprNode());
3701 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata();
3702 metadata->setEcmaName(ecmaName());
3703 metadata->setClassSource(m_classSource);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003704 constructor = generator.emitNode(dst, m_constructorExpression);
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003705 if (m_classHeritage) {
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003706 needsHomeObject = true;
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003707 RefPtr<RegisterID> isDerivedConstructor = generator.newTemporary();
3708 generator.emitUnaryOp(op_not, isDerivedConstructor.get(),
3709 generator.emitUnaryOp(op_eq_null, isDerivedConstructor.get(), superclass.get()));
3710 generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), isDerivedConstructor.get(), PropertyNode::Unknown);
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003711 } else if (metadata->superBinding() == SuperBinding::Needed)
3712 needsHomeObject = true;
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003713 } else {
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003714 if (m_classHeritage) {
3715 constructor = generator.finalDestination(dst);
3716 RefPtr<RegisterID> tempRegister = generator.newTemporary();
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003717 Ref<Label> superclassIsNullLabel = generator.newLabel();
3718 Ref<Label> done = generator.newLabel();
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003719
3720 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3721 generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Extends, m_name, ecmaName(), m_classSource);
3722 generator.emitLoad(tempRegister.get(), jsBoolean(true));
3723 generator.emitJump(done.get());
3724 generator.emitLabel(superclassIsNullLabel.get());
3725 generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3726 generator.emitLoad(tempRegister.get(), jsBoolean(false));
3727 generator.emitLabel(done.get());
3728 generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), tempRegister.get(), PropertyNode::Unknown);
3729 } else {
3730 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
3731 ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3732 }
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003733 }
3734
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003735 const auto& propertyNames = generator.propertyNames();
3736 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003737
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003738 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003739 RefPtr<RegisterID> protoParent = generator.newTemporary();
3740 generator.emitLoad(protoParent.get(), jsNull());
3741
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003742 RefPtr<RegisterID> tempRegister = generator.newTemporary();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003743
3744 // FIXME: Throw TypeError if it's a generator function.
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003745 Ref<Label> superclassIsUndefinedLabel = generator.newLabel();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003746 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
3747
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003748 Ref<Label> superclassIsNullLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003749 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3750
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003751 Ref<Label> superclassIsObjectLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003752 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003753 generator.emitLabel(superclassIsUndefinedLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003754 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3755 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003756 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
3757
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003758 Ref<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003759 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
keith_miller@apple.com02373132016-01-14 20:45:48 +00003760 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_function, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
3761 generator.emitThrowTypeError(ASCIILiteral("The value of the superclass's prototype property is not an object."));
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003762 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
3763
3764 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003765 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003766 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003767 }
3768
gskachkov@gmail.com82b84582017-01-20 11:43:24 +00003769 if (needsHomeObject)
3770 emitPutHomeObject(generator, constructor.get(), prototype.get());
3771
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003772 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003773 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +00003774 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003775
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003776 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
utatane.tea@gmail.com4a9d9562016-10-04 22:51:38 +00003777 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003778
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003779 if (m_staticMethods)
3780 generator.emitNode(constructor.get(), m_staticMethods);
3781
3782 if (m_instanceMethods)
3783 generator.emitNode(prototype.get(), m_instanceMethods);
3784
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003785 if (!m_name.isNull()) {
3786 Variable classNameVar = generator.variable(m_name);
3787 RELEASE_ASSERT(classNameVar.isResolved());
3788 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
sbarati@apple.come67fd782016-04-19 01:38:30 +00003789 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003790 generator.popLexicalScope(this);
3791 }
3792
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003793 return generator.moveToDestinationIfNeeded(dst, constructor.get());
3794}
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003795
3796// ------------------------------ ImportDeclarationNode -----------------------
3797
3798void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3799{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003800 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003801}
3802
3803// ------------------------------ ExportAllDeclarationNode --------------------
3804
3805void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3806{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003807 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003808}
3809
3810// ------------------------------ ExportDefaultDeclarationNode ----------------
3811
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003812void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003813{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003814 ASSERT(m_declaration);
3815 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003816}
3817
3818// ------------------------------ ExportLocalDeclarationNode ------------------
3819
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003820void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003821{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003822 ASSERT(m_declaration);
3823 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003824}
3825
3826// ------------------------------ ExportNamedDeclarationNode ------------------
3827
3828void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3829{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003830 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003831}
3832
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003833// ------------------------------ DestructuringAssignmentNode -----------------
3834RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
oliver@apple.comd055db62013-10-02 19:11:04 +00003835{
3836 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
3837 return result;
3838 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
3839 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00003840 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003841 return generator.moveToDestinationIfNeeded(dst, initializer.get());
3842}
3843
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003844static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
3845{
3846 ASSERT(defaultValue);
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003847 Ref<Label> isNotUndefined = generator.newLabel();
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003848 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
3849 generator.emitNode(maybeUndefined, defaultValue);
3850 generator.emitLabel(isNotUndefined.get());
3851}
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003852
oliver@apple.com47784d62013-10-25 21:31:36 +00003853void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003854{
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003855 RefPtr<RegisterID> iterator = generator.newTemporary();
3856 {
3857 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
3858 CallArguments args(generator, nullptr);
3859 generator.emitMove(args.thisRegister(), rhs);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003860 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003861 }
3862
utatane.tea@gmail.coma5c94332015-06-23 00:51:44 +00003863 if (m_targetPatterns.isEmpty()) {
3864 generator.emitIteratorClose(iterator.get(), this);
3865 return;
3866 }
3867
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003868 RefPtr<RegisterID> done;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003869 for (auto& target : m_targetPatterns) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003870 switch (target.bindingType) {
3871 case BindingType::Elision:
3872 case BindingType::Element: {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003873 Ref<Label> iterationSkipped = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003874 if (!done)
3875 done = generator.newTemporary();
3876 else
3877 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003878
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003879 RefPtr<RegisterID> value = generator.newTemporary();
3880 generator.emitIteratorNext(value.get(), iterator.get(), this);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003881 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003882 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
3883 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003884
3885 {
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003886 Ref<Label> valueIsSet = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003887 generator.emitJump(valueIsSet.get());
3888 generator.emitLabel(iterationSkipped.get());
3889 generator.emitLoad(value.get(), jsUndefined());
3890 generator.emitLabel(valueIsSet.get());
3891 }
3892
3893 if (target.bindingType == BindingType::Element) {
3894 if (target.defaultValue)
3895 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
3896 target.pattern->bindValue(generator, value.get());
3897 }
3898 break;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003899 }
3900
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003901 case BindingType::RestElement: {
3902 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
3903
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003904 Ref<Label> iterationDone = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003905 if (!done)
3906 done = generator.newTemporary();
3907 else
3908 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3909
3910 RefPtr<RegisterID> index = generator.newTemporary();
3911 generator.emitLoad(index.get(), jsNumber(0));
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003912 Ref<Label> loopStart = generator.newLabel();
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003913 generator.emitLabel(loopStart.get());
3914
3915 RefPtr<RegisterID> value = generator.newTemporary();
3916 generator.emitIteratorNext(value.get(), iterator.get(), this);
3917 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
3918 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3919 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
3920
3921 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
3922 generator.emitInc(index.get());
3923 generator.emitJump(loopStart.get());
3924
3925 generator.emitLabel(iterationDone.get());
3926 target.pattern->bindValue(generator, array.get());
3927 break;
3928 }
3929 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003930 }
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003931
utatane.tea@gmail.com6f1b3f32017-02-16 07:56:48 +00003932 Ref<Label> iteratorClosed = generator.newLabel();
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003933 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
3934 generator.emitIteratorClose(iterator.get(), this);
3935 generator.emitLabel(iteratorClosed.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003936}
3937
3938RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
3939{
oliver@apple.comd055db62013-10-02 19:11:04 +00003940 if (!rhs->isSimpleArray())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003941 return nullptr;
3942
3943 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
3944 Vector<ExpressionNode*> elements;
3945 for (; elementNodes; elementNodes = elementNodes->next()) {
3946 ExpressionNode* value = elementNodes->value();
3947 if (value->isSpreadExpression())
3948 return nullptr;
3949 elements.append(value);
3950 }
oliver@apple.com47784d62013-10-25 21:31:36 +00003951
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003952 RefPtr<RegisterID> resultRegister;
3953 if (dst && dst != generator.ignoredResult())
3954 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00003955 if (m_targetPatterns.size() != elements.size())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003956 return nullptr;
oliver@apple.comd055db62013-10-02 19:11:04 +00003957 Vector<RefPtr<RegisterID>> registers;
3958 registers.reserveCapacity(m_targetPatterns.size());
3959 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3960 registers.uncheckedAppend(generator.newTemporary());
3961 generator.emitNode(registers.last().get(), elements[i]);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003962 if (m_targetPatterns[i].defaultValue)
3963 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003964 if (resultRegister)
3965 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003966 }
3967
3968 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003969 if (m_targetPatterns[i].pattern)
3970 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003971 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003972 if (resultRegister)
3973 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00003974 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00003975}
3976
3977void ArrayPatternNode::toString(StringBuilder& builder) const
3978{
3979 builder.append('[');
3980 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003981 const auto& target = m_targetPatterns[i];
3982
3983 switch (target.bindingType) {
3984 case BindingType::Elision:
oliver@apple.comd055db62013-10-02 19:11:04 +00003985 builder.append(',');
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003986 break;
3987
3988 case BindingType::Element:
3989 target.pattern->toString(builder);
3990 if (i < m_targetPatterns.size() - 1)
3991 builder.append(',');
3992 break;
3993
3994 case BindingType::RestElement:
commit-queue@webkit.org57101852016-08-12 00:33:47 +00003995 builder.appendLiteral("...");
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003996 target.pattern->toString(builder);
3997 break;
oliver@apple.comd055db62013-10-02 19:11:04 +00003998 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003999 }
4000 builder.append(']');
4001}
4002
4003void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4004{
4005 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.comc497d152015-07-17 18:48:30 +00004006 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
oliver@apple.comd055db62013-10-02 19:11:04 +00004007 node->collectBoundIdentifiers(identifiers);
4008 }
4009}
4010
4011void ObjectPatternNode::toString(StringBuilder& builder) const
4012{
4013 builder.append('{');
4014 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00004015 if (m_targetPatterns[i].wasString)
akling@apple.coma9904fb2015-05-08 08:44:23 +00004016 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00004017 else
oliver@apple.comd055db62013-10-02 19:11:04 +00004018 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00004019 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00004020 m_targetPatterns[i].pattern->toString(builder);
4021 if (i < m_targetPatterns.size() - 1)
4022 builder.append(',');
4023 }
4024 builder.append('}');
4025}
4026
oliver@apple.com47784d62013-10-25 21:31:36 +00004027void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00004028{
commit-queue@webkit.org4d3e0c22015-12-01 20:11:20 +00004029 generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
annulen@yandex.ru23120122016-12-20 18:26:10 +00004030 for (const auto& target : m_targetPatterns) {
oliver@apple.comd055db62013-10-02 19:11:04 +00004031 RefPtr<RegisterID> temp = generator.newTemporary();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00004032 if (!target.propertyExpression) {
4033 // Should not emit get_by_id for indexed ones.
utatane.tea@gmail.com43926962016-11-27 06:08:16 +00004034 std::optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00004035 if (!optionalIndex)
4036 generator.emitGetById(temp.get(), rhs, target.propertyName);
4037 else {
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00004038 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00004039 generator.emitGetByVal(temp.get(), rhs, index.get());
4040 }
4041 } else {
commit-queue@webkit.org38980282015-11-25 01:43:14 +00004042 RefPtr<RegisterID> propertyName = generator.emitNode(target.propertyExpression);
4043 generator.emitGetByVal(temp.get(), rhs, propertyName.get());
4044 }
4045
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00004046 if (target.defaultValue)
4047 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
oliver@apple.com47784d62013-10-25 21:31:36 +00004048 target.pattern->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00004049 }
4050}
4051
4052void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4053{
4054 for (size_t i = 0; i < m_targetPatterns.size(); i++)
4055 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
4056}
4057
oliver@apple.com47784d62013-10-25 21:31:36 +00004058void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00004059{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004060 Variable var = generator.variable(m_boundProperty);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004061 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004062 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004063 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4064 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004065 if (isReadOnly) {
4066 generator.emitReadOnlyExceptionIfNeeded(var);
4067 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00004068 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004069 generator.emitMove(local, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00004070 generator.emitProfileType(local, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004071 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004072 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00004073 return;
4074 }
4075 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00004076 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004077 RegisterID* scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00004078 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004079 if (m_bindingContext == AssignmentContext::AssignmentExpression)
4080 generator.emitTDZCheckIfNecessary(var, nullptr, scope);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00004081 if (isReadOnly) {
4082 generator.emitReadOnlyExceptionIfNeeded(var);
4083 return;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004084 }
sbarati@apple.come67fd782016-04-19 01:38:30 +00004085 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00004086 generator.emitProfileType(value, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00004087 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00004088 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00004089 return;
4090}
4091
4092void BindingNode::toString(StringBuilder& builder) const
4093{
4094 builder.append(m_boundProperty.string());
4095}
4096
4097void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4098{
4099 identifiers.append(m_boundProperty);
4100}
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004101
4102void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
4103{
4104}
4105
4106void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
4107{
4108 if (m_assignmentTarget->isResolveNode()) {
4109 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
4110 Variable var = generator.variable(lhs->identifier());
4111 bool isReadOnly = var.isReadOnly();
4112 if (RegisterID* local = var.local()) {
4113 generator.emitTDZCheckIfNecessary(var, local, nullptr);
4114
4115 if (isReadOnly)
4116 generator.emitReadOnlyExceptionIfNeeded(var);
4117 else {
4118 generator.invalidateForInContextForLocal(local);
4119 generator.moveToDestinationIfNeeded(local, value);
4120 generator.emitProfileType(local, divotStart(), divotEnd());
4121 }
4122 return;
4123 }
4124 if (generator.isStrictMode())
4125 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4126 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
4127 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
4128 if (isReadOnly) {
4129 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
4130 if (threwException)
4131 return;
4132 }
4133 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
4134 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00004135 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004136 generator.emitProfileType(value, var, divotStart(), divotEnd());
4137 }
4138 } else if (m_assignmentTarget->isDotAccessorNode()) {
4139 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
4140 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4141 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00004142 if (lhs->base()->isSuperNode()) {
4143 RefPtr<RegisterID> thisValue = generator.ensureThis();
4144 generator.emitPutById(base.get(), thisValue.get(), lhs->identifier(), value);
4145 } else
4146 generator.emitPutById(base.get(), lhs->identifier(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004147 generator.emitProfileType(value, divotStart(), divotEnd());
4148 } else if (m_assignmentTarget->isBracketAccessorNode()) {
4149 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
4150 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
4151 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(lhs->subscript(), true, false);
4152 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00004153 if (lhs->base()->isSuperNode()) {
4154 RefPtr<RegisterID> thisValue = generator.ensureThis();
4155 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
4156 } else
4157 generator.emitPutByVal(base.get(), property.get(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00004158 generator.emitProfileType(value, divotStart(), divotEnd());
4159 }
4160}
4161
4162void AssignmentElementNode::toString(StringBuilder& builder) const
4163{
4164 if (m_assignmentTarget->isResolveNode())
4165 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
4166}
4167
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004168void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4169{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004170 m_pattern->collectBoundIdentifiers(identifiers);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004171}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004172
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004173void RestParameterNode::toString(StringBuilder& builder) const
4174{
commit-queue@webkit.org57101852016-08-12 00:33:47 +00004175 builder.appendLiteral("...");
sbarati@apple.com6a686122016-08-03 07:50:40 +00004176 m_pattern->toString(builder);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004177}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004178
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004179void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
4180{
4181 RELEASE_ASSERT_NOT_REACHED();
4182}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004183
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004184void RestParameterNode::emit(BytecodeGenerator& generator)
4185{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004186 RefPtr<RegisterID> temp = generator.newTemporary();
4187 generator.emitRestParameter(temp.get(), m_numParametersToSkip);
4188 m_pattern->bindValue(generator, temp.get());
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004189}
4190
4191
oliver@apple.com72f8a822013-10-17 01:02:34 +00004192RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4193{
4194 RELEASE_ASSERT_NOT_REACHED();
4195 return 0;
4196}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00004197
4198} // namespace JSC