blob: f82836ca94d8cefb1b3005c83cddc135e0444e0b [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
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +000074void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
75{
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
ggaren@apple.com81c68cc2013-04-27 06:43:33 +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();
97 if (value == MixedTriState)
98 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
99 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
100 generator.emitJump(trueTarget);
101 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
102 generator.emitJump(falseTarget);
103
104 // All other cases are unconditional fall-throughs, like "if (true)".
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000105}
106
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000107RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000108{
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000109 if (dst == generator.ignoredResult())
110 return 0;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000111 return generator.emitLoad(dst, jsValue(generator));
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000112}
113
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000114JSValue StringNode::jsValue(BytecodeGenerator& generator) const
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000115{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000116 return generator.addStringConstant(m_value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000117}
118
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000119// ------------------------------ NumberNode ----------------------------------
120
121RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
122{
123 if (dst == generator.ignoredResult())
124 return nullptr;
125 return generator.emitLoad(dst, jsValue(generator), isIntegerNode() ? SourceCodeRepresentation::Integer : SourceCodeRepresentation::Double);
126}
127
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000128// ------------------------------ RegExpNode -----------------------------------
129
130RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
131{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000132 if (dst == generator.ignoredResult())
133 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000134 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 +0000135}
136
137// ------------------------------ ThisNode -------------------------------------
138
139RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
140{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000141 generator.ensureThis();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000142 if (dst == generator.ignoredResult())
143 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000144
145 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000146 static const unsigned thisLength = 4;
147 generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000148 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000149}
150
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000151// ------------------------------ SuperNode -------------------------------------
152
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000153static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000154{
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000155 if (generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {
156 RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000157 return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().builtinNames().homeObjectPrivateName());
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000158 }
159
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000160 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000161 callee.setIndex(CallFrameSlot::callee);
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000162 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().builtinNames().homeObjectPrivateName());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000163}
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000164
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000165static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
166{
167 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000168 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
169}
170
sbarati@apple.com23315d62016-05-09 20:17:23 +0000171static RegisterID* emitGetSuperFunctionForConstruct(BytecodeGenerator& generator)
172{
173 if (generator.isDerivedConstructorContext())
174 return generator.emitGetById(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(), generator.propertyNames().underscoreProto);
175
176 RegisterID callee;
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000177 callee.setIndex(CallFrameSlot::callee);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000178 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().underscoreProto);
179}
180
181RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
182{
183 RegisterID* result = emitSuperBaseForCallee(generator);
184 return generator.moveToDestinationIfNeeded(generator.finalDestination(dst), result);
185}
186
commit-queue@webkit.org17f99e42015-07-21 18:18:42 +0000187// ------------------------------ NewTargetNode ----------------------------------
188
189RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
190{
191 if (dst == generator.ignoredResult())
192 return nullptr;
193
194 return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
195}
196
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000197// ------------------------------ ResolveNode ----------------------------------
198
199bool ResolveNode::isPure(BytecodeGenerator& generator) const
200{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000201 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000202}
203
204RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
205{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000206 Variable var = generator.variable(m_ident);
207 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000208 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000209 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000210 return nullptr;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000211
212 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000213 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000214 }
215
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000216 JSTextPosition divot = m_start + m_ident.length();
217 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000218 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000219 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000220 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000221 generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000222 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000223 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000224}
225
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000226// ------------------------------ TemplateStringNode -----------------------------------
227
228RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
229{
230 if (dst == generator.ignoredResult())
231 return nullptr;
232 return generator.emitLoad(dst, JSValue(generator.addStringConstant(cooked())));
233}
234
235// ------------------------------ TemplateLiteralNode -----------------------------------
236
237RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
238{
239 if (!m_templateExpressions) {
240 TemplateStringNode* templateString = m_templateStrings->value();
241 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
242 return generator.emitNode(dst, templateString);
243 }
244
245 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
246
247 TemplateStringListNode* templateString = m_templateStrings;
248 TemplateExpressionListNode* templateExpression = m_templateExpressions;
249 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
250 // Evaluate TemplateString.
251 if (!templateString->value()->cooked().isEmpty()) {
252 temporaryRegisters.append(generator.newTemporary());
253 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
254 }
255
256 // Evaluate Expression.
257 temporaryRegisters.append(generator.newTemporary());
258 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
259 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
260 }
261
262 // Evaluate tail TemplateString.
263 if (!templateString->value()->cooked().isEmpty()) {
264 temporaryRegisters.append(generator.newTemporary());
265 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
266 }
267
oliver@apple.com1aec7c72016-06-13 23:17:00 +0000268 if (temporaryRegisters.size() == 1)
269 return generator.emitToString(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get());
270
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000271 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
272}
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000273
274// ------------------------------ TaggedTemplateNode -----------------------------------
275
276RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
277{
278 ExpectedFunction expectedFunction = NoExpectedFunction;
279 RefPtr<RegisterID> tag = nullptr;
280 RefPtr<RegisterID> base = nullptr;
281 if (!m_tag->isLocation()) {
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000282 tag = generator.newTemporary();
283 tag = generator.emitNode(tag.get(), m_tag);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000284 } else if (m_tag->isResolveNode()) {
285 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
286 const Identifier& identifier = resolve->identifier();
287 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
288
289 Variable var = generator.variable(identifier);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000290 if (RegisterID* local = var.local()) {
291 generator.emitTDZCheckIfNecessary(var, local, nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000292 tag = generator.emitMove(generator.newTemporary(), local);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000293 } else {
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000294 tag = generator.newTemporary();
295 base = generator.newTemporary();
296
297 JSTextPosition newDivot = divotStart() + identifier.length();
298 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
299 generator.moveToDestinationIfNeeded(base.get(), generator.emitResolveScope(base.get(), var));
300 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000301 generator.emitTDZCheckIfNecessary(var, tag.get(), nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000302 }
303 } else if (m_tag->isBracketAccessorNode()) {
304 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000305 base = generator.newTemporary();
306 base = generator.emitNode(base.get(), bracket->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000307 RefPtr<RegisterID> property = generator.emitNode(bracket->subscript());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000308 if (bracket->base()->isSuperNode()) {
309 RefPtr<RegisterID> thisValue = generator.ensureThis();
310 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
311 } else
312 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000313 } else {
314 ASSERT(m_tag->isDotAccessorNode());
315 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000316 base = generator.newTemporary();
317 base = generator.emitNode(base.get(), dot->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000318 if (dot->base()->isSuperNode()) {
319 RefPtr<RegisterID> thisValue = generator.ensureThis();
320 tag = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), dot->identifier());
321 } else
322 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000323 }
324
325 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(generator.newTemporary(), this);
326
327 unsigned expressionsCount = 0;
328 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
329 ++expressionsCount;
330
331 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
332 if (base)
333 generator.emitMove(callArguments.thisRegister(), base.get());
334 else
335 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
336
337 unsigned argumentIndex = 0;
338 generator.emitMove(callArguments.argumentRegister(argumentIndex++), templateObject.get());
339 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
340 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
341
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000342 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 +0000343}
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000344
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000345// ------------------------------ ArrayNode ------------------------------------
346
347RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
348{
349 // FIXME: Should we put all of this code into emitNewArray?
350
351 unsigned length = 0;
352 ElementNode* firstPutElement;
353 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000354 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000355 break;
356 ++length;
357 }
358
359 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000360 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000361
oliver@apple.coma991d692011-06-14 23:39:25 +0000362 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000363 ElementNode* n = firstPutElement;
364 for (; n; n = n->next()) {
365 if (n->value()->isSpreadExpression())
366 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000367 RegisterID* value = generator.emitNode(n->value());
368 length += n->elision();
369 generator.emitPutByIndex(array.get(), length++, value);
370 }
371
372 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000373 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000374 generator.emitPutById(array.get(), generator.propertyNames().length, value);
375 }
376
377 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000378
379handleSpread:
380 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
381 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
382 {
oliver@apple.come050d642013-10-19 00:09:28 +0000383 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000384 generator.emitInc(index.get());
385 };
386 for (; n; n = n->next()) {
387 if (n->elision())
388 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
389 if (n->value()->isSpreadExpression()) {
390 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
391 generator.emitEnumeration(spread, spread->expression(), spreader);
392 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000393 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000394 generator.emitInc(index.get());
395 }
396 }
397
398 if (m_elision) {
399 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
400 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
401 }
402 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000403}
404
405bool ArrayNode::isSimpleArray() const
406{
407 if (m_elision || m_optional)
408 return false;
409 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
410 if (ptr->elision())
411 return false;
commit-queue@webkit.org1a78b432016-09-15 01:14:45 +0000412 if (ptr->value()->isSpreadExpression())
413 return false;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000414 }
415 return true;
416}
417
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000418ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000419{
420 ASSERT(!m_elision && !m_optional);
421 ElementNode* ptr = m_element;
422 if (!ptr)
423 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000424 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000425 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000426 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000427 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000428 ArgumentListNode* tail = head;
429 ptr = ptr->next();
430 for (; ptr; ptr = ptr->next()) {
431 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000432 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000433 }
434 return head;
435}
436
437// ------------------------------ ObjectLiteralNode ----------------------------
438
439RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
440{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000441 if (!m_list) {
442 if (dst == generator.ignoredResult())
443 return 0;
444 return generator.emitNewObject(generator.finalDestination(dst));
445 }
446 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
447 generator.emitNode(newObj.get(), m_list);
448 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000449}
450
451// ------------------------------ PropertyListNode -----------------------------
452
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000453static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
454{
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +0000455 generator.emitPutById(function, generator.propertyNames().builtinNames().homeObjectPrivateName(), homeObject);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000456}
457
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000458RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
459{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000460 // Fast case: this loop just handles regular value properties.
461 PropertyListNode* p = this;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000462 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000463 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000464
465 // Were there any get/set properties?
466 if (p) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000467 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
468 // a computed property, just emit everything as that may override previous values.
469 bool hasComputedProperty = false;
470
barraclough@apple.com09a55682012-01-30 18:28:39 +0000471 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000472 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000473 GetterSetterMap map;
474
475 // Build a map, pairing get/set values together.
476 for (PropertyListNode* q = p; q; q = q->m_next) {
477 PropertyNode* node = q->m_node;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000478 if (node->m_type & PropertyNode::Computed) {
479 hasComputedProperty = true;
480 break;
481 }
482 if (node->m_type & PropertyNode::Constant)
barraclough@apple.com09a55682012-01-30 18:28:39 +0000483 continue;
484
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000485 // Duplicates are possible.
486 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
oliver@apple.com72d38322013-10-21 19:23:24 +0000487 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000488 if (!result.isNewEntry) {
489 if (result.iterator->value.first->m_type == node->m_type)
490 result.iterator->value.first = node;
491 else
492 result.iterator->value.second = node;
493 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000494 }
495
496 // Iterate over the remaining properties in the list.
497 for (; p; p = p->m_next) {
498 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000499
500 // Handle regular values.
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000501 if (node->m_type & PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000502 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000503 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000504 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000505
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000506 RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000507 bool needsSuperBinding = node->needsSuperBinding();
508 if (needsSuperBinding)
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000509 emitPutHomeObject(generator, value.get(), dst);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000510
511 unsigned attributes = node->isClassProperty() ? (Accessor | DontEnum) : Accessor;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000512
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000513 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
514
515 // This is a get/set property which may be overridden by a computed property later.
516 if (hasComputedProperty) {
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000517 // Computed accessors.
518 if (node->m_type & PropertyNode::Computed) {
519 RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000520 generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000521 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000522 generator.emitPutGetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000523 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000524 generator.emitPutSetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000525 continue;
526 }
527
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000528 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000529 generator.emitPutGetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000530 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000531 generator.emitPutSetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000532 continue;
533 }
534
535 // This is a get/set property pair.
oliver@apple.com72d38322013-10-21 19:23:24 +0000536 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000537 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000538 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000539
540 // Was this already generated as a part of its partner?
541 if (pair.second == node)
542 continue;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000543
barraclough@apple.com09a55682012-01-30 18:28:39 +0000544 // Generate the paired node now.
545 RefPtr<RegisterID> getterReg;
546 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000547 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000548
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000549 if (node->m_type & PropertyNode::Getter) {
barraclough@apple.com09a55682012-01-30 18:28:39 +0000550 getterReg = value;
551 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000552 ASSERT(pair.second->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000553 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000554 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000555 } else {
556 setterReg = generator.newTemporary();
557 generator.emitLoad(setterReg.get(), jsUndefined());
558 }
559 } else {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000560 ASSERT(node->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000561 setterReg = value;
562 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000563 ASSERT(pair.second->m_type & PropertyNode::Getter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000564 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000565 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000566 } else {
567 getterReg = generator.newTemporary();
568 generator.emitLoad(getterReg.get(), jsUndefined());
569 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000570 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000571
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000572 ASSERT(!pair.second || needsSuperBinding == pair.second->needsSuperBinding());
573 if (needsSuperBinding && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000574 emitPutHomeObject(generator, secondReg, dst);
575
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000576 generator.emitPutGetterSetter(dst, *node->name(), attributes, getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000577 }
578 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000579
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000580 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000581}
582
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000583void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
584{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000585 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000586 if (node.needsSuperBinding())
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000587 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000588
utatane.tea@gmail.com9b114152016-09-18 17:40:11 +0000589 if (node.isClassProperty()) {
590 ASSERT(node.needsSuperBinding());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000591 RefPtr<RegisterID> propertyNameRegister;
592 if (node.name())
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000593 propertyNameRegister = generator.emitLoad(nullptr, *node.name());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000594 else
595 propertyNameRegister = generator.emitNode(node.m_expression);
596
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000597 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000598 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(), value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000599 return;
600 }
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000601 if (const auto* identifier = node.name()) {
602 Optional<uint32_t> optionalIndex = parseIndex(*identifier);
603 if (!optionalIndex) {
604 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
605 return;
606 }
607
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +0000608 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000609 generator.emitDirectPutByVal(newObj, index.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000610 return;
611 }
612 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000613 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000614 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000615}
616
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000617// ------------------------------ BracketAccessorNode --------------------------------
618
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000619static bool isNonIndexStringElement(ExpressionNode& element)
620{
621 return element.isString() && !parseIndex(static_cast<StringNode&>(element).value());
622}
623
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000624RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
625{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000626 if (m_base->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000627 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
628 RefPtr<RegisterID> thisValue = generator.ensureThis();
629 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000630 if (isNonIndexStringElement(*m_subscript)) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000631 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
sbarati@apple.com23315d62016-05-09 20:17:23 +0000632 generator.emitGetById(finalDest.get(), superBase.get(), thisValue.get(), id);
633 } else {
634 RefPtr<RegisterID> subscript = generator.emitNode(m_subscript);
635 generator.emitGetByVal(finalDest.get(), superBase.get(), thisValue.get(), subscript.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000636 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000637
638 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
639 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
640 return finalDest.get();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000641 }
642
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000643 RegisterID* ret;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000644 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000645
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000646 if (isNonIndexStringElement(*m_subscript)) {
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000647 RefPtr<RegisterID> base = generator.emitNode(m_base);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000648 ret = generator.emitGetById(finalDest.get(), base.get(), static_cast<StringNode*>(m_subscript)->value());
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000649 } else {
650 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
651 RegisterID* property = generator.emitNode(m_subscript);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000652 ret = generator.emitGetByVal(finalDest.get(), base.get(), property);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000653 }
654
655 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
656
sbarati@apple.com23315d62016-05-09 20:17:23 +0000657 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000658 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000659}
660
661// ------------------------------ DotAccessorNode --------------------------------
662
663RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
664{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000665 bool baseIsSuper = m_base->isSuperNode();
666 RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000667 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000668 RegisterID* finalDest = generator.finalDestination(dst);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000669 RegisterID* ret;
670 if (baseIsSuper) {
671 RefPtr<RegisterID> thisValue = generator.ensureThis();
672 ret = generator.emitGetById(finalDest, base.get(), thisValue.get(), m_ident);
673 } else
674 ret = generator.emitGetById(finalDest, base.get(), m_ident);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000675 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000676 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000677}
678
679// ------------------------------ ArgumentListNode -----------------------------
680
681RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
682{
683 ASSERT(m_expr);
684 return generator.emitNode(dst, m_expr);
685}
686
687// ------------------------------ NewExprNode ----------------------------------
688
689RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
690{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000691 ExpectedFunction expectedFunction;
692 if (m_expr->isResolveNode())
693 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
694 else
695 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000696 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000697 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000698 CallArguments callArguments(generator, m_args);
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000699 generator.emitMove(callArguments.thisRegister(), func.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000700 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000701}
702
oliver@apple.com72f8a822013-10-17 01:02:34 +0000703CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000704 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000705 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000706{
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000707 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000708 if (argumentsNode) {
709 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
710 ++argumentCountIncludingThis;
711 }
712
713 m_argv.grow(argumentCountIncludingThis);
714 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
715 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000716 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 +0000717 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000718
719 // We need to ensure that the frame size is stack-aligned
mark.lam@apple.com2bd89342016-07-08 22:58:15 +0000720 while ((CallFrame::headerSizeInRegisters + m_argv.size()) % stackAlignmentRegisters()) {
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000721 m_argv.insert(0, generator.newTemporary());
722 m_padding++;
723 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000724
725 while (stackOffset() % stackAlignmentRegisters()) {
726 m_argv.insert(0, generator.newTemporary());
727 m_padding++;
728 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000729}
730
731// ------------------------------ EvalFunctionCallNode ----------------------------------
732
733RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
734{
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000735 // We need try to load 'this' before call eval in constructor, because 'this' can created by 'super' in some of the arrow function
736 // var A = class A {
737 // constructor () { this.id = 'A'; }
738 // }
739 //
740 // var B = class B extend A {
741 // constructor () {
742 // var arrow = () => super();
743 // arrow();
744 // eval("this.id = 'B'");
745 // }
746 // }
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000747 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000748 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
749
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000750 Variable var = generator.variable(generator.propertyNames().eval);
751 if (RegisterID* local = var.local()) {
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000752 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000753 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000754 CallArguments callArguments(generator, m_args);
755 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000756 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
oliver@apple.com58c86752013-07-25 04:02:40 +0000757 }
758
759 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000760 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000761 JSTextPosition newDivot = divotStart() + 4;
762 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000763 generator.moveToDestinationIfNeeded(
764 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000765 generator.emitResolveScope(callArguments.thisRegister(), var));
766 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
sbarati@apple.com56c95ce2016-06-29 22:34:03 +0000767 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000768 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000769}
770
771// ------------------------------ FunctionCallValueNode ----------------------------------
772
773RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
774{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000775 if (m_expr->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000776 RefPtr<RegisterID> func = emitGetSuperFunctionForConstruct(generator);
777 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
778 CallArguments callArguments(generator, m_args);
779
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000780 ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000781 ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000782 generator.emitMove(callArguments.thisRegister(), generator.newTarget());
783 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000784
sbarati@apple.com8a1620b62016-08-03 01:28:16 +0000785 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000786 bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
787
788 if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction()))
789 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
790
791 RefPtr<Label> thisIsEmptyLabel = generator.newLabel();
792 generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get());
793 generator.emitThrowReferenceError(ASCIILiteral("'super()' can't be called more than once in a constructor."));
794 generator.emitLabel(thisIsEmptyLabel.get());
795
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000796 generator.emitMove(generator.thisRegister(), ret);
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000797
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000798 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor)
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000799 generator.emitPutThisToArrowFunctionContextScope();
commit-queue@webkit.orgabdc6172016-02-24 20:46:44 +0000800
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000801 return ret;
802 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000803 RefPtr<RegisterID> func = generator.emitNode(m_expr);
804 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
805 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000806 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000807 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000808 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000809 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000810}
811
812// ------------------------------ FunctionCallResolveNode ----------------------------------
813
814RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
815{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000816 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000817
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000818 Variable var = generator.variable(m_ident);
819 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000820 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000821 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000822 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000823 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000824 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000825 // This passes NoExpectedFunction because we expect that if the function is in a
826 // local variable, then it's not one of our built-in constructors.
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000827 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000828 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000829 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000830 }
831
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000832 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000833 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000834 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000835
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000836 JSTextPosition newDivot = divotStart() + m_ident.length();
837 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000838 generator.moveToDestinationIfNeeded(
839 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000840 generator.emitResolveScope(callArguments.thisRegister(), var));
841 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000842 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000843 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000844 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000845 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000846}
847
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000848// ------------------------------ BytecodeIntrinsicNode ----------------------------------
849
850RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
851{
852 return (this->*m_emitter)(generator, dst);
853}
854
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +0000855RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator& generator, RegisterID* dst)
856{
857 ASSERT(!m_args->m_listNode);
858
859 return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
860}
861
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +0000862RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator& generator, RegisterID* dst)
863{
864#ifndef NDEBUG
865 ArgumentListNode* node = m_args->m_listNode;
866 RefPtr<RegisterID> condition = generator.emitNode(node);
867 generator.emitAssert(condition.get(), node->firstLine());
868 return dst;
869#else
870 UNUSED_PARAM(generator);
871 return dst;
872#endif
873}
874
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000875RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
876{
877 ArgumentListNode* node = m_args->m_listNode;
878 RefPtr<RegisterID> base = generator.emitNode(node);
879 node = node->m_next;
880 RefPtr<RegisterID> index = generator.emitNode(node);
881 node = node->m_next;
882 RefPtr<RegisterID> value = generator.emitNode(node);
883
884 ASSERT(!node->m_next);
885
886 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
887}
888
keith_miller@apple.come497e202016-06-13 21:05:36 +0000889RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator& generator, RegisterID* dst)
890{
891 ArgumentListNode* node = m_args->m_listNode;
892 RefPtr<RegisterID> function = generator.emitNode(node);
893 node = node->m_next;
894 RefPtr<RegisterID> thisRegister = generator.emitNode(node);
895 ASSERT(!node->m_next);
896
897 RefPtr<RegisterID> finalDst = generator.finalDestination(dst);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +0000898 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 +0000899}
900
keith_miller@apple.com8844d302016-04-07 19:38:00 +0000901RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
902{
903 ArgumentListNode* node = m_args->m_listNode;
904 RefPtr<RegisterID> base = generator.emitNode(node);
905 node = node->m_next;
906
907 // Since this is a builtin we expect the creator to use a string literal as the second argument.
908 ASSERT(node->m_expr->isString());
909 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
910 ASSERT(!node->m_next);
911
keith_miller@apple.come497e202016-06-13 21:05:36 +0000912 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
913 return generator.emitTryGetById(finalDest.get(), base.get(), ident);
keith_miller@apple.com8844d302016-04-07 19:38:00 +0000914}
915
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +0000916RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toNumber(BytecodeGenerator& generator, RegisterID* dst)
917{
918 ArgumentListNode* node = m_args->m_listNode;
919 RefPtr<RegisterID> src = generator.emitNode(node);
920 ASSERT(!node->m_next);
921
922 return generator.moveToDestinationIfNeeded(dst, generator.emitToNumber(generator.tempDestination(dst), src.get()));
923}
924
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +0000925RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
926{
927 ArgumentListNode* node = m_args->m_listNode;
928 RefPtr<RegisterID> src = generator.emitNode(node);
929 ASSERT(!node->m_next);
930
931 return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
932}
keith_miller@apple.com5bed6f62016-06-16 06:01:47 +0000933
934RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isJSArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
935{
936 ArgumentListNode* node = m_args->m_listNode;
937 RefPtr<RegisterID> src = generator.emitNode(node);
938 ASSERT(!node->m_next);
939
940 return generator.moveToDestinationIfNeeded(dst, generator.emitIsJSArray(generator.tempDestination(dst), src.get()));
941}
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +0000942
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +0000943RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
944{
945 ArgumentListNode* node = m_args->m_listNode;
946 RefPtr<RegisterID> src = generator.emitNode(node);
947 ASSERT(!node->m_next);
948
949 return generator.moveToDestinationIfNeeded(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
950}
951
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +0000952RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
953{
954 ArgumentListNode* node = m_args->m_listNode;
955 RefPtr<RegisterID> src = generator.emitNode(node);
956 ASSERT(!node->m_next);
957
958 return generator.moveToDestinationIfNeeded(dst, generator.emitIsRegExpObject(generator.tempDestination(dst), src.get()));
959}
960
utatane.tea@gmail.com0f56f572016-02-08 23:14:47 +0000961RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
962{
963 ArgumentListNode* node = m_args->m_listNode;
964 RefPtr<RegisterID> src = generator.emitNode(node);
965 ASSERT(!node->m_next);
966
967 return generator.moveToDestinationIfNeeded(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
968}
969
utatane.tea@gmail.com4a748b12016-09-17 06:32:50 +0000970RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
971{
972 ArgumentListNode* node = m_args->m_listNode;
973 RefPtr<RegisterID> src = generator.emitNode(node);
974 ASSERT(!node->m_next);
975
976 return generator.moveToDestinationIfNeeded(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
977}
978
utatane.tea@gmail.comda89adb2016-09-19 18:46:07 +0000979RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isMap(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
980{
981 ArgumentListNode* node = m_args->m_listNode;
982 RefPtr<RegisterID> src = generator.emitNode(node);
983 ASSERT(!node->m_next);
984
985 return generator.moveToDestinationIfNeeded(dst, generator.emitIsMap(generator.tempDestination(dst), src.get()));
986}
987
988RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isSet(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
989{
990 ArgumentListNode* node = m_args->m_listNode;
991 RefPtr<RegisterID> src = generator.emitNode(node);
992 ASSERT(!node->m_next);
993
994 return generator.moveToDestinationIfNeeded(dst, generator.emitIsSet(generator.tempDestination(dst), src.get()));
995}
996
sbarati@apple.com3cc67a72016-08-18 17:17:41 +0000997RegisterID* BytecodeIntrinsicNode::emit_intrinsic_newArrayWithSize(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
998{
999 ArgumentListNode* node = m_args->m_listNode;
1000 RefPtr<RegisterID> size = generator.emitNode(node);
1001 ASSERT(!node->m_next);
1002
1003 RefPtr<RegisterID> finalDestination = generator.finalDestination(dst);
1004 generator.emitNewArrayWithSize(finalDestination.get(), size.get());
1005 return finalDestination.get();
1006}
1007
utatane.tea@gmail.combf8978b2016-02-02 19:33:05 +00001008
1009#define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \
1010 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_##name(BytecodeGenerator& generator, RegisterID* dst) \
1011 { \
1012 ASSERT(!m_args); \
1013 ASSERT(type() == Type::Constant); \
1014 if (dst == generator.ignoredResult()) \
1015 return nullptr; \
1016 return generator.emitLoad(dst, generator.vm()->bytecodeIntrinsicRegistry().name##Value(generator)); \
1017 }
1018 JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
1019#undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
1020
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001021// ------------------------------ FunctionCallBracketNode ----------------------------------
1022
1023RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1024{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001025 bool baseIsSuper = m_base->isSuperNode();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001026 bool subscriptIsNonIndexString = isNonIndexStringElement(*m_subscript);
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001027
1028 RefPtr<RegisterID> base;
1029 if (baseIsSuper)
1030 base = emitSuperBaseForCallee(generator);
1031 else {
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001032 if (subscriptIsNonIndexString)
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001033 base = generator.emitNode(m_base);
1034 else
1035 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
1036 }
1037
1038 RefPtr<RegisterID> function;
sbarati@apple.com23315d62016-05-09 20:17:23 +00001039 RefPtr<RegisterID> thisRegister;
1040 if (baseIsSuper) {
1041 // 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.
1042 thisRegister = generator.ensureThis();
1043 }
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00001044 if (subscriptIsNonIndexString) {
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001045 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001046 if (baseIsSuper)
1047 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisRegister.get(), static_cast<StringNode*>(m_subscript)->value());
1048 else
1049 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001050 } else {
1051 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
1052 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001053 if (baseIsSuper)
1054 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisRegister.get(), property.get());
1055 else
1056 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +00001057 }
1058
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001059 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001060 CallArguments callArguments(generator, m_args);
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001061 if (baseIsSuper) {
1062 generator.emitTDZCheck(generator.thisRegister());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001063 generator.emitMove(callArguments.thisRegister(), thisRegister.get());
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +00001064 } else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001065 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001066 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001067 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001068 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001069}
1070
1071// ------------------------------ FunctionCallDotNode ----------------------------------
1072
1073RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1074{
1075 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001076 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001077 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001078 bool baseIsSuper = m_base->isSuperNode();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001079 if (baseIsSuper)
1080 generator.emitMove(callArguments.thisRegister(), generator.ensureThis());
1081 else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001082 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001083 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001084 if (baseIsSuper) {
1085 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
1086 generator.emitGetById(function.get(), superBase.get(), callArguments.thisRegister(), m_ident);
1087 } else
1088 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001089 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001090 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001091 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001092}
1093
1094RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1095{
1096 RefPtr<Label> realCall = generator.newLabel();
1097 RefPtr<Label> end = generator.newLabel();
1098 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001099 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001100 RefPtr<RegisterID> function;
oliver@apple.comba848d12014-02-12 17:14:23 +00001101 bool emitCallCheck = !generator.isBuiltinFunction();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001102 if (emitCallCheck) {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001103 if (m_base->isSuperNode()) {
1104 RefPtr<RegisterID> thisValue = generator.ensureThis();
1105 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().callPublicName());
1106 } else
1107 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +00001108 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001109 }
1110 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001111 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001112 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 +00001113 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
1114 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001115 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001116 argumentsRegister = generator.emitNode(subject);
1117 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
1118 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001119 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 +00001120 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001121 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001122 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +00001123
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001124 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1125 CallArguments callArguments(generator, m_args);
1126 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001127 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001128 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001129 } else {
1130 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1131 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +00001132 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001133 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001134 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001135 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001136 if (emitCallCheck) {
1137 generator.emitJump(end.get());
1138 generator.emitLabel(realCall.get());
1139 {
1140 CallArguments callArguments(generator, m_args);
1141 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001142 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001143 }
1144 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001145 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001146 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001147 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001148}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001149
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001150static bool areTrivialApplyArguments(ArgumentsNode* args)
1151{
1152 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
1153 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
1154}
1155
1156RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1157{
1158 // A few simple cases can be trivially handled as ordinary function calls.
1159 // function.apply(), function.apply(arg) -> identical to function.call
1160 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
1161 bool mayBeCall = areTrivialApplyArguments(m_args);
1162
1163 RefPtr<Label> realCall = generator.newLabel();
1164 RefPtr<Label> end = generator.newLabel();
1165 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001166 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001167 RefPtr<RegisterID> function;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001168 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001169 bool emitCallCheck = !generator.isBuiltinFunction();
1170 if (emitCallCheck) {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001171 if (m_base->isSuperNode()) {
1172 RefPtr<RegisterID> thisValue = generator.ensureThis();
1173 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().applyPublicName());
1174 } else
1175 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +00001176 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
1177 }
1178 if (mayBeCall) {
1179 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
1180 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001181 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
1182 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001183 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
1184 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
1185 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1186 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1187
1188 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
1189 {
1190 RefPtr<Label> haveThis = generator.newLabel();
1191 RefPtr<Label> end = generator.newLabel();
1192 RefPtr<RegisterID> compareResult = generator.newTemporary();
1193 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1194 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
1195 generator.emitMove(thisRegister.get(), value);
1196 generator.emitLoad(index.get(), jsNumber(1));
1197 generator.emitJump(end.get());
1198 generator.emitLabel(haveThis.get());
1199 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1200 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
1201 generator.emitMove(argumentsRegister.get(), value);
1202 generator.emitLoad(index.get(), jsNumber(2));
1203 generator.emitLabel(end.get());
1204 };
1205 generator.emitEnumeration(this, spread->expression(), extractor);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001206 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 +00001207 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +00001208 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
1209 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +00001210 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 +00001211 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1212 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +00001213 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001214 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001215 } else {
1216 m_args->m_listNode = m_args->m_listNode->m_next;
1217 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1218 CallArguments callArguments(generator, m_args);
1219 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001220 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001221 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001222 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001223 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +00001224 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001225 CallArguments callArguments(generator, m_args);
1226 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001227 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001228 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001229 } else {
1230 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
oliver@apple.comba848d12014-02-12 17:14:23 +00001231 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1232 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
1233 RefPtr<RegisterID> argsRegister;
1234 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001235 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +00001236
1237 // Function.prototype.apply ignores extra arguments, but we still
1238 // need to evaluate them for side effects.
1239 while ((args = args->m_next))
1240 generator.emitNode(args->m_expr);
1241
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001242 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 +00001243 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001244 if (emitCallCheck) {
1245 generator.emitJump(end.get());
1246 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001247 CallArguments callArguments(generator, m_args);
1248 generator.emitMove(callArguments.thisRegister(), base.get());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00001249 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd(), DebuggableCall::Yes);
oliver@apple.comba848d12014-02-12 17:14:23 +00001250 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001251 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001252 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001253 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001254}
1255
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001256// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001257
ggaren@apple.comf3036112013-04-27 23:14:04 +00001258static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001259{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001260 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001261}
1262
1263static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1264{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001265 if (dst == srcDst)
1266 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1267 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1268 emitIncOrDec(generator, srcDst, oper);
1269 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001270}
1271
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001272RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001273{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001274 if (dst == generator.ignoredResult())
1275 return PrefixNode::emitResolve(generator, dst);
1276
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001277 ASSERT(m_expr->isResolveNode());
1278 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1279 const Identifier& ident = resolve->identifier();
1280
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001281 Variable var = generator.variable(ident);
1282 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001283 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001284 RefPtr<RegisterID> localReg = local;
1285 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001286 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001287 localReg = generator.emitMove(generator.tempDestination(dst), local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001288 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001289 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1290 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1291 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001292 }
oliver@apple.com75f804e2013-03-07 00:25:20 +00001293
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001294 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001295 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1296 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001297 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001298 if (var.isReadOnly()) {
1299 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1300 if (threwException)
1301 return value.get();
1302 }
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001303 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001304 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001305 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001306 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1307 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001308
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001309 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001310}
1311
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001312RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001313{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001314 if (dst == generator.ignoredResult())
1315 return PrefixNode::emitBracket(generator, dst);
1316
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001317 ASSERT(m_expr->isBracketAccessorNode());
1318 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1319 ExpressionNode* baseNode = bracketAccessor->base();
1320 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001321
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001322 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001323 RefPtr<RegisterID> property = generator.emitNode(subscript);
1324
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001325 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001326 RefPtr<RegisterID> value;
1327 RefPtr<RegisterID> thisValue;
1328 if (baseNode->isSuperNode()) {
1329 thisValue = generator.ensureThis();
1330 value = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
1331 } else
1332 value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001333 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001334 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001335 if (baseNode->isSuperNode())
1336 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value.get());
1337 else
1338 generator.emitPutByVal(base.get(), property.get(), value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001339 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001340 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001341}
1342
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001343RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001344{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001345 if (dst == generator.ignoredResult())
1346 return PrefixNode::emitDot(generator, dst);
1347
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001348 ASSERT(m_expr->isDotAccessorNode());
1349 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1350 ExpressionNode* baseNode = dotAccessor->base();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001351 bool baseIsSuper = baseNode->isSuperNode();
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001352 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001353
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001354 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1355
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001356 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001357 RefPtr<RegisterID> value;
1358 RefPtr<RegisterID> thisValue;
1359 if (baseIsSuper) {
1360 thisValue = generator.ensureThis();
1361 value = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), ident);
1362 } else
1363 value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001364 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001365 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001366 if (baseIsSuper)
1367 generator.emitPutById(base.get(), thisValue.get(), ident, value.get());
1368 else
1369 generator.emitPutById(base.get(), ident, value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001370 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001371 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001372}
1373
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001374RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001375{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001376 if (m_expr->isResolveNode())
1377 return emitResolve(generator, dst);
1378
1379 if (m_expr->isBracketAccessorNode())
1380 return emitBracket(generator, dst);
1381
1382 if (m_expr->isDotAccessorNode())
1383 return emitDot(generator, dst);
1384
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001385 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001386 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1387 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001388}
1389
1390// ------------------------------ DeleteResolveNode -----------------------------------
1391
1392RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1393{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001394 Variable var = generator.variable(m_ident);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001395 if (var.local()) {
1396 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001397 return generator.emitLoad(generator.finalDestination(dst), false);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001398 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001399
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001400 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001401 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001402 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
oliver@apple.com58c86752013-07-25 04:02:40 +00001403 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001404}
1405
1406// ------------------------------ DeleteBracketNode -----------------------------------
1407
1408RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1409{
1410 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001411 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001412
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001413 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001414 if (m_base->isSuperNode())
1415 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001416 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001417}
1418
1419// ------------------------------ DeleteDotNode -----------------------------------
1420
1421RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1422{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001423 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001424
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001425 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001426 if (m_base->isSuperNode())
1427 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001428 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001429}
1430
1431// ------------------------------ DeleteValueNode -----------------------------------
1432
1433RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1434{
1435 generator.emitNode(generator.ignoredResult(), m_expr);
1436
1437 // delete on a non-location expression ignores the value and returns true
1438 return generator.emitLoad(generator.finalDestination(dst), true);
1439}
1440
1441// ------------------------------ VoidNode -------------------------------------
1442
1443RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1444{
1445 if (dst == generator.ignoredResult()) {
1446 generator.emitNode(generator.ignoredResult(), m_expr);
1447 return 0;
1448 }
1449 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1450 return generator.emitLoad(dst, jsUndefined());
1451}
1452
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001453// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001454
1455RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1456{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001457 Variable var = generator.variable(m_ident);
1458 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001459 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001460 if (dst == generator.ignoredResult())
1461 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001462 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001463 }
1464
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001465 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1466 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001467 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001468 if (dst == generator.ignoredResult())
1469 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001470 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001471}
1472
1473// ------------------------------ TypeOfValueNode -----------------------------------
1474
1475RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1476{
1477 if (dst == generator.ignoredResult()) {
1478 generator.emitNode(generator.ignoredResult(), m_expr);
1479 return 0;
1480 }
1481 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1482 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1483}
1484
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001485// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001486
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001487RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001488{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001489 ASSERT(m_expr->isResolveNode());
1490 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1491 const Identifier& ident = resolve->identifier();
1492
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001493 Variable var = generator.variable(ident);
1494 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001495 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001496 RefPtr<RegisterID> localReg = local;
1497 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001498 generator.emitReadOnlyExceptionIfNeeded(var);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001499 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001500 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001501 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001502 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001503 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001504 generator.emitMove(localReg.get(), tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001505 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001506 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1507 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001508 emitIncOrDec(generator, localReg.get(), m_operator);
1509 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001510 }
1511
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001512 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001513 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1514 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001515 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001516 if (var.isReadOnly()) {
1517 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1518 if (threwException)
1519 return value.get();
1520 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001521
oliver@apple.com58c86752013-07-25 04:02:40 +00001522 emitIncOrDec(generator, value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001523 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001524 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001525 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1526 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001527 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001528}
1529
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001530RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001531{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001532 ASSERT(m_expr->isBracketAccessorNode());
1533 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1534 ExpressionNode* baseNode = bracketAccessor->base();
1535 ExpressionNode* subscript = bracketAccessor->subscript();
1536
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001537 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001538 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001539 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1540
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001541 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001542 RegisterID* value;
1543 RefPtr<RegisterID> thisValue;
1544 if (baseNode->isSuperNode()) {
1545 thisValue = generator.ensureThis();
1546 value = generator.emitGetByVal(propDst.get(), base.get(), thisValue.get(), property.get());
1547 } else
1548 value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001549 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001550 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001551 if (baseNode->isSuperNode())
1552 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
1553 else
1554 generator.emitPutByVal(base.get(), property.get(), value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001555 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001556 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1557}
1558
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001559RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001560{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001561 ASSERT(m_expr->isDotAccessorNode());
1562 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1563 ExpressionNode* baseNode = dotAccessor->base();
1564 const Identifier& ident = dotAccessor->identifier();
1565
1566 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001567 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1568
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001569 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001570 RegisterID* value;
1571 RefPtr<RegisterID> thisValue;
1572 if (baseNode->isSuperNode()) {
1573 thisValue = generator.ensureThis();
1574 value = generator.emitGetById(propDst.get(), base.get(), thisValue.get(), ident);
1575 } else
1576 value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001577 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001578 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001579 if (baseNode->isSuperNode())
1580 generator.emitPutById(base.get(), thisValue.get(), ident, value);
1581 else
1582 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001583 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001584 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1585}
1586
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001587RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001588{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001589 if (m_expr->isResolveNode())
1590 return emitResolve(generator, dst);
1591
1592 if (m_expr->isBracketAccessorNode())
1593 return emitBracket(generator, dst);
1594
1595 if (m_expr->isDotAccessorNode())
1596 return emitDot(generator, dst);
1597
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001598 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001599 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1600 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001601}
1602
1603// ------------------------------ Unary Operation Nodes -----------------------------------
1604
1605RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1606{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001607 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001608 generator.emitExpressionInfo(position(), position(), position());
commit-queue@webkit.org4c2202a2016-09-23 03:50:22 +00001609 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), OperandTypes(m_expr->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001610}
1611
utatane.tea@gmail.comdb32c542016-06-30 15:26:47 +00001612// ------------------------------ UnaryPlusNode -----------------------------------
1613
1614RegisterID* UnaryPlusNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1615{
1616 ASSERT(opcodeID() == op_to_number);
1617 RefPtr<RegisterID> src = generator.emitNode(expr());
1618 generator.emitExpressionInfo(position(), position(), position());
1619 return generator.emitToNumber(generator.finalDestination(dst), src.get());
1620}
1621
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001622// ------------------------------ BitwiseNotNode -----------------------------------
1623
1624RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1625{
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00001626 RefPtr<RegisterID> src2 = generator.emitLoad(nullptr, jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001627 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1628 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 +00001629}
1630
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001631// ------------------------------ LogicalNotNode -----------------------------------
1632
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001633void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001634{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001635 // reverse the true and false targets
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001636 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001637}
1638
1639
1640// ------------------------------ Binary Operation Nodes -----------------------------------
1641
1642// BinaryOpNode::emitStrcat:
1643//
1644// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1645// more values, where we can determine a set of separate op_add operations would be operating on
1646// string values.
1647//
1648// This function expects to be operating on a graph of AST nodes looking something like this:
1649//
1650// (a)... (b)
1651// \ /
1652// (+) (c)
1653// \ /
1654// [d] ((+))
1655// \ /
1656// [+=]
1657//
1658// The assignment operation is optional, if it exists the register holding the value on the
1659// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1660//
1661// The method should be called on the node at the root of the tree of regular binary add
1662// operations (marked in the diagram with a double set of parentheses). This node must
1663// be performing a string concatenation (determined by statically detecting that at least
1664// one child must be a string).
1665//
1666// Since the minimum number of values being concatenated together is expected to be 3, if
1667// a lhs to a concatenating assignment is not provided then the root add should have at
1668// least one left child that is also an add that can be determined to be operating on strings.
1669//
1670RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1671{
1672 ASSERT(isAdd());
1673 ASSERT(resultDescriptor().definitelyIsString());
1674
1675 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1676 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1677 // added first, and the leftmost child is never added, so the vector produced for the
1678 // example above will be [ c, b ].
1679 Vector<ExpressionNode*, 16> reverseExpressionList;
1680 reverseExpressionList.append(m_expr2);
1681
1682 // Examine the left child of the add. So long as this is a string add, add its right-child
1683 // to the list, and keep processing along the left fork.
1684 ExpressionNode* leftMostAddChild = m_expr1;
1685 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1686 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1687 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1688 }
1689
1690 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1691
1692 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1693 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1694 // op_strcat node handle its conversion if required).
1695 if (lhs)
1696 temporaryRegisters.append(generator.newTemporary());
1697
1698 // Emit code for the leftmost node ((a) in the example).
1699 temporaryRegisters.append(generator.newTemporary());
1700 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1701 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1702
1703 // Note on ordering of conversions:
1704 //
1705 // We maintain the same ordering of conversions as we would see if the concatenations
1706 // was performed as a sequence of adds (otherwise this optimization could change
1707 // behaviour should an object have been provided a valueOf or toString method).
1708 //
1709 // Considering the above example, the sequnce of execution is:
1710 // * evaluate operand (a)
1711 // * evaluate operand (b)
1712 // * convert (a) to primitive <- (this would be triggered by the first add)
1713 // * convert (b) to primitive <- (ditto)
1714 // * evaluate operand (c)
1715 // * convert (c) to primitive <- (this would be triggered by the second add)
1716 // And optionally, if there is an assignment:
1717 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1718 //
1719 // As such we do not plant an op to convert the leftmost child now. Instead, use
1720 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1721 // once the second node has been generated. However, if the leftmost child is an
1722 // immediate we can trivially determine that no conversion will be required.
1723 // If this is the case
1724 if (leftMostAddChild->isString())
1725 leftMostAddChildTempRegister = 0;
1726
1727 while (reverseExpressionList.size()) {
1728 ExpressionNode* node = reverseExpressionList.last();
1729 reverseExpressionList.removeLast();
1730
1731 // Emit the code for the current node.
1732 temporaryRegisters.append(generator.newTemporary());
1733 generator.emitNode(temporaryRegisters.last().get(), node);
1734
1735 // On the first iteration of this loop, when we first reach this point we have just
1736 // generated the second node, which means it is time to convert the leftmost operand.
1737 if (leftMostAddChildTempRegister) {
1738 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1739 leftMostAddChildTempRegister = 0; // Only do this once.
1740 }
1741 // Plant a conversion for this node, if necessary.
1742 if (!node->isString())
1743 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1744 }
1745 ASSERT(temporaryRegisters.size() >= 3);
1746
1747 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1748 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1749 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001750 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001751 // If there is an assignment convert the lhs now. This will also copy lhs to
1752 // the temporary register we allocated for it.
1753 if (lhs)
1754 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1755
1756 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1757}
1758
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001759void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1760{
1761 TriState branchCondition;
1762 ExpressionNode* branchExpression;
1763 tryFoldToBranch(generator, branchCondition, branchExpression);
1764
1765 if (branchCondition == MixedTriState)
1766 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1767 else if (branchCondition == TrueTriState)
1768 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1769 else
1770 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1771}
1772
1773static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1774{
1775 ResultType expressionType = branchExpression->resultDescriptor();
1776
1777 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1778 return true;
1779 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1780 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1781 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1782 return true;
1783
1784 return false;
1785}
1786
1787void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1788{
1789 branchCondition = MixedTriState;
1790 branchExpression = 0;
1791
1792 ConstantNode* constant = 0;
1793 if (m_expr1->isConstant()) {
1794 constant = static_cast<ConstantNode*>(m_expr1);
1795 branchExpression = m_expr2;
1796 } else if (m_expr2->isConstant()) {
1797 constant = static_cast<ConstantNode*>(m_expr2);
1798 branchExpression = m_expr1;
1799 }
1800
1801 if (!constant)
1802 return;
1803 ASSERT(branchExpression);
1804
1805 OpcodeID opcodeID = this->opcodeID();
1806 JSValue value = constant->jsValue(generator);
1807 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1808 if (!canFoldToBranch)
1809 return;
1810
1811 if (opcodeID == op_eq || opcodeID == op_stricteq)
1812 branchCondition = triState(value.pureToBoolean());
1813 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1814 branchCondition = triState(!value.pureToBoolean());
1815}
1816
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001817RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1818{
1819 OpcodeID opcodeID = this->opcodeID();
1820
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001821 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001822 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001823 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001824 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001825
1826 if (opcodeID == op_neq) {
1827 if (m_expr1->isNull() || m_expr2->isNull()) {
1828 RefPtr<RegisterID> src = generator.tempDestination(dst);
1829 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1830 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1831 }
1832 }
1833
oliver@apple.comece74042012-12-01 00:50:39 +00001834 ExpressionNode* left = m_expr1;
1835 ExpressionNode* right = m_expr2;
1836 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1837 if (left->isString())
1838 std::swap(left, right);
1839 }
1840
1841 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001842 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001843 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001844 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001845 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001846 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1847 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001848 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001849 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001850 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001851 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001852 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001853 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1854 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001855 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 +00001856 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1857 return generator.emitUnaryOp(op_unsigned, result, result);
1858 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001859}
1860
1861RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1862{
1863 if (m_expr1->isNull() || m_expr2->isNull()) {
1864 RefPtr<RegisterID> src = generator.tempDestination(dst);
1865 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1866 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1867 }
1868
oliver@apple.comece74042012-12-01 00:50:39 +00001869 ExpressionNode* left = m_expr1;
1870 ExpressionNode* right = m_expr2;
1871 if (left->isString())
1872 std::swap(left, right);
1873
1874 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001875 RefPtr<RegisterID> src2 = generator.emitNode(right);
1876 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001877}
1878
1879RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1880{
oliver@apple.comece74042012-12-01 00:50:39 +00001881 ExpressionNode* left = m_expr1;
1882 ExpressionNode* right = m_expr2;
1883 if (left->isString())
1884 std::swap(left, right);
1885
1886 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001887 RefPtr<RegisterID> src2 = generator.emitNode(right);
1888 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001889}
1890
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001891RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1892{
1893 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001894 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001895 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001896 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 +00001897}
1898
1899RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1900{
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001901 RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
1902 RefPtr<RegisterID> isObject = generator.newTemporary();
1903 RefPtr<RegisterID> isCustom = generator.newTemporary();
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001904 RefPtr<RegisterID> prototype = generator.newTemporary();
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001905 RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1906 RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
1907 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
1908 RefPtr<Label> custom = generator.newLabel();
1909 RefPtr<Label> done = generator.newLabel();
1910 RefPtr<Label> typeError = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001911
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001912 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001913 generator.emitIsObject(isObject.get(), constructor.get());
1914 generator.emitJumpIfFalse(isObject.get(), typeError.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001915
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001916 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001917 generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001918
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001919 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001920 generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
1921
1922 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1923 generator.emitJumpIfTrue(isCustom.get(), custom.get());
1924
1925 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1926 generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
1927
1928 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1929 generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
1930
1931 generator.emitJump(done.get());
1932
1933 generator.emitLabel(typeError.get());
1934 generator.emitThrowTypeError("Right hand side of instanceof is not an object");
1935
1936 generator.emitLabel(custom.get());
1937
1938 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1939 generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
1940
1941 generator.emitLabel(done.get());
1942
1943 return dstReg.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001944}
1945
1946// ------------------------------ LogicalOpNode ----------------------------
1947
1948RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1949{
1950 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1951 RefPtr<Label> target = generator.newLabel();
1952
1953 generator.emitNode(temp.get(), m_expr1);
1954 if (m_operator == OpLogicalAnd)
1955 generator.emitJumpIfFalse(temp.get(), target.get());
1956 else
1957 generator.emitJumpIfTrue(temp.get(), target.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001958 generator.emitNodeInTailPosition(temp.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001959 generator.emitLabel(target.get());
1960
1961 return generator.moveToDestinationIfNeeded(dst, temp.get());
1962}
1963
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001964void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001965{
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001966 RefPtr<Label> afterExpr1 = generator.newLabel();
1967 if (m_operator == OpLogicalAnd)
1968 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1969 else
1970 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1971 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001972
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001973 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001974}
1975
1976// ------------------------------ ConditionalNode ------------------------------
1977
1978RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1979{
1980 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1981 RefPtr<Label> beforeElse = generator.newLabel();
1982 RefPtr<Label> afterElse = generator.newLabel();
1983
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001984 RefPtr<Label> beforeThen = generator.newLabel();
1985 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1986 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001987
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001988 generator.emitProfileControlFlow(m_expr1->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001989 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001990 generator.emitJump(afterElse.get());
1991
1992 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001993 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001994 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001995
1996 generator.emitLabel(afterElse.get());
1997
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001998 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001999
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002000 return newDst.get();
2001}
2002
2003// ------------------------------ ReadModifyResolveNode -----------------------------------
2004
2005// FIXME: should this be moved to be a method on BytecodeGenerator?
2006static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
2007{
2008 OpcodeID opcodeID;
2009 switch (oper) {
2010 case OpMultEq:
2011 opcodeID = op_mul;
2012 break;
2013 case OpDivEq:
2014 opcodeID = op_div;
2015 break;
2016 case OpPlusEq:
2017 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
2018 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
2019 opcodeID = op_add;
2020 break;
2021 case OpMinusEq:
2022 opcodeID = op_sub;
2023 break;
2024 case OpLShift:
2025 opcodeID = op_lshift;
2026 break;
2027 case OpRShift:
2028 opcodeID = op_rshift;
2029 break;
2030 case OpURShift:
2031 opcodeID = op_urshift;
2032 break;
2033 case OpAndEq:
2034 opcodeID = op_bitand;
2035 break;
2036 case OpXOrEq:
2037 opcodeID = op_bitxor;
2038 break;
2039 case OpOrEq:
2040 opcodeID = op_bitor;
2041 break;
2042 case OpModEq:
2043 opcodeID = op_mod;
2044 break;
utatane.tea@gmail.come9906382016-07-21 07:33:28 +00002045 case OpPowEq:
2046 opcodeID = op_pow;
2047 break;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002048 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00002049 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002050 return dst;
2051 }
2052
2053 RegisterID* src2 = generator.emitNode(m_right);
2054
2055 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
2056 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
2057 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002058 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00002059 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
2060 if (oper == OpURShift)
2061 return generator.emitUnaryOp(op_unsigned, result, result);
2062 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002063}
2064
2065RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2066{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00002067 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002068 Variable var = generator.variable(m_ident);
2069 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002070 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002071 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002072 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002073 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2074 generator.emitProfileType(result, divotStart(), divotEnd());
2075 return result;
ggaren@apple.com6e309822012-09-05 21:44:43 +00002076 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002077
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002078 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002079 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002080 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002081 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002082 generator.emitMove(local, result.get());
2083 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002084 generator.emitProfileType(local, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002085 return generator.moveToDestinationIfNeeded(dst, result.get());
2086 }
2087
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002088 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2089 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002090 generator.emitProfileType(result, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002091 return generator.moveToDestinationIfNeeded(dst, result);
2092 }
2093
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002094 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002095 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2096 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002097 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002098 if (var.isReadOnly()) {
2099 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2100 if (threwException)
2101 return value.get();
2102 }
oliver@apple.com58c86752013-07-25 04:02:40 +00002103 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 +00002104 RegisterID* returnResult = result.get();
2105 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002106 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002107 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2108 }
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002109 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002110}
2111
sbarati@apple.come67fd782016-04-19 01:38:30 +00002112static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
2113{
2114 switch (assignmentContext) {
2115 case AssignmentContext::DeclarationStatement:
2116 return InitializationMode::Initialization;
2117 case AssignmentContext::ConstDeclarationStatement:
2118 return InitializationMode::ConstInitialization;
2119 case AssignmentContext::AssignmentExpression:
2120 return InitializationMode::NotInitialization;
2121 }
2122
2123 ASSERT_NOT_REACHED();
2124 return InitializationMode::NotInitialization;
2125}
2126
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002127// ------------------------------ AssignResolveNode -----------------------------------
2128
2129RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2130{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002131 Variable var = generator.variable(m_ident);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002132 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002133 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002134 RegisterID* result = nullptr;
2135 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2136 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002137
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002138 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002139 result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002140 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002141 generator.emitProfileType(result, var, divotStart(), divotEnd());
2142 } else if (var.isSpecial()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002143 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
2144 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002145 generator.emitMove(local, tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002146 generator.emitProfileType(local, var, divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002147 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002148 result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
2149 } else {
2150 RegisterID* right = generator.emitNode(local, m_right);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002151 generator.emitProfileType(right, var, divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002152 generator.invalidateForInContextForLocal(local);
2153 result = generator.moveToDestinationIfNeeded(dst, right);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002154 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002155
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002156 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002157 generator.liftTDZCheckIfPossible(var);
2158 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002159 }
2160
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002161 if (generator.isStrictMode())
2162 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002163 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002164 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2165 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002166 if (dst == generator.ignoredResult())
2167 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00002168 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002169 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002170 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002171 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2172 if (threwException)
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002173 return result;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002174 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002175 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002176 RegisterID* returnResult = result.get();
2177 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002178 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002179 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2180 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002181
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002182 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002183 generator.liftTDZCheckIfPossible(var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002184 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002185}
2186
2187// ------------------------------ AssignDotNode -----------------------------------
2188
2189RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2190{
2191 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2192 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002193 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002194 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002195 RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
2196 if (m_base->isSuperNode()) {
2197 RefPtr<RegisterID> thisValue = generator.ensureThis();
2198 generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
2199 } else
2200 generator.emitPutById(base.get(), m_ident, forwardResult.get());
2201 generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
2202 return generator.moveToDestinationIfNeeded(dst, forwardResult.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002203}
2204
2205// ------------------------------ ReadModifyDotNode -----------------------------------
2206
2207RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2208{
2209 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2210
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002211 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002212 RefPtr<RegisterID> value;
2213 RefPtr<RegisterID> thisValue;
2214 if (m_base->isSuperNode()) {
2215 thisValue = generator.ensureThis();
2216 value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
2217 } else
2218 value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002219 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 +00002220
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002221 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002222 RegisterID* ret;
2223 if (m_base->isSuperNode())
2224 ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
2225 else
2226 ret = generator.emitPutById(base.get(), m_ident, updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002227 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002228 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002229}
2230
2231// ------------------------------ AssignErrorNode -----------------------------------
2232
2233RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2234{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002235 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002236}
2237
2238// ------------------------------ AssignBracketNode -----------------------------------
2239
2240RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2241{
2242 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2243 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2244 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002245 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002246
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002247 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002248 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00002249
sbarati@apple.com23315d62016-05-09 20:17:23 +00002250 if (isNonIndexStringElement(*m_subscript)) {
2251 if (m_base->isSuperNode()) {
2252 RefPtr<RegisterID> thisValue = generator.ensureThis();
2253 generator.emitPutById(base.get(), thisValue.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2254 } else
2255 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2256 } else {
2257 if (m_base->isSuperNode()) {
2258 RefPtr<RegisterID> thisValue = generator.ensureThis();
2259 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), forwardResult);
2260 } else
2261 generator.emitPutByVal(base.get(), property.get(), forwardResult);
2262 }
akling@apple.come09d0422014-11-13 19:18:43 +00002263
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002264 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00002265 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002266}
2267
2268// ------------------------------ ReadModifyBracketNode -----------------------------------
2269
2270RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2271{
2272 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2273 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2274
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002275 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002276 RefPtr<RegisterID> value;
2277 RefPtr<RegisterID> thisValue;
2278 if (m_base->isSuperNode()) {
2279 thisValue = generator.ensureThis();
2280 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisValue.get(), property.get());
2281 } else
2282 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002283 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 +00002284
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002285 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002286 if (m_base->isSuperNode())
2287 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), updatedValue);
2288 else
2289 generator.emitPutByVal(base.get(), property.get(), updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002290 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002291
2292 return updatedValue;
2293}
2294
2295// ------------------------------ CommaNode ------------------------------------
2296
2297RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2298{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002299 CommaNode* node = this;
2300 for (; node && node->next(); node = node->next())
2301 generator.emitNode(generator.ignoredResult(), node->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002302 return generator.emitNodeInTailPosition(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002303}
2304
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002305// ------------------------------ SourceElements -------------------------------
2306
2307
2308inline StatementNode* SourceElements::lastStatement() const
2309{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002310 return m_tail;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002311}
2312
2313inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2314{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002315 for (StatementNode* statement = m_head; statement; statement = statement->next())
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002316 generator.emitNodeInTailPosition(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002317}
2318
2319// ------------------------------ BlockNode ------------------------------------
2320
2321inline StatementNode* BlockNode::lastStatement() const
2322{
2323 return m_statements ? m_statements->lastStatement() : 0;
2324}
2325
ggaren@apple.comddc6f102015-03-20 20:12:10 +00002326StatementNode* BlockNode::singleStatement() const
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002327{
2328 return m_statements ? m_statements->singleStatement() : 0;
2329}
2330
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002331void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002332{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002333 if (!m_statements)
2334 return;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002335 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002336 m_statements->emitBytecode(generator, dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002337 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002338}
2339
2340// ------------------------------ EmptyStatementNode ---------------------------
2341
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002342void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002343{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002344 generator.emitDebugHook(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002345}
2346
2347// ------------------------------ DebuggerStatementNode ---------------------------
2348
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002349void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002350{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002351 generator.emitDebugHook(DidReachBreakpoint, position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002352}
2353
2354// ------------------------------ ExprStatementNode ----------------------------
2355
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002356void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002357{
2358 ASSERT(m_expr);
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002359 generator.emitDebugHook(this);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002360 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002361}
2362
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002363// ------------------------------ DeclarationStatement ----------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002364
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002365void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002366{
2367 ASSERT(m_expr);
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002368 generator.emitDebugHook(this);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002369 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002370}
2371
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002372// ------------------------------ EmptyVarExpression ----------------------------
2373
2374RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2375{
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002376 // 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 +00002377 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002378 return nullptr;
2379
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002380 Variable var = generator.variable(m_ident);
2381 if (RegisterID* local = var.local())
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002382 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002383 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002384 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2385 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002386 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002387 }
2388
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002389 return nullptr;
2390}
2391
2392// ------------------------------ EmptyLetExpression ----------------------------
2393
2394RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2395{
2396 // Lexical declarations like 'let' must move undefined into their variables so we don't
2397 // get TDZ errors for situations like this: `let x; x;`
2398 Variable var = generator.variable(m_ident);
2399 if (RegisterID* local = var.local()) {
2400 generator.emitLoad(local, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002401 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002402 } else {
2403 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2404 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002405 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002406 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002407 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002408
sbarati@apple.coma5cf2f12016-03-29 22:11:24 +00002409 generator.liftTDZCheckIfPossible(var);
2410
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002411 // 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 +00002412 return nullptr;
2413}
2414
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002415// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002416
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002417static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002418{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002419 if (statementNode->isBlock())
2420 return static_cast<BlockNode*>(statementNode)->singleStatement();
2421 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002422}
2423
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002424bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2425 Label*& trueTarget, FallThroughMode& fallThroughMode)
2426{
2427 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2428 if (!singleStatement)
2429 return false;
2430
2431 if (singleStatement->isBreak()) {
2432 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2433 Label* target = breakNode->trivialTarget(generator);
2434 if (!target)
2435 return false;
2436 trueTarget = target;
2437 fallThroughMode = FallThroughMeansFalse;
2438 return true;
2439 }
2440
2441 if (singleStatement->isContinue()) {
2442 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2443 Label* target = continueNode->trivialTarget(generator);
2444 if (!target)
2445 return false;
2446 trueTarget = target;
2447 fallThroughMode = FallThroughMeansFalse;
2448 return true;
2449 }
2450
2451 return false;
2452}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002453
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002454void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002455{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002456 generator.emitDebugHook(m_condition, WillExecuteStatement);
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00002457
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002458 RefPtr<Label> beforeThen = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002459 RefPtr<Label> beforeElse = generator.newLabel();
2460 RefPtr<Label> afterElse = generator.newLabel();
2461
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002462 Label* trueTarget = beforeThen.get();
2463 Label* falseTarget = beforeElse.get();
2464 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2465 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2466
2467 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002468 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002469 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002470
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002471 if (!didFoldIfBlock) {
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002472 generator.emitNodeInTailPosition(dst, m_ifBlock);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002473 if (m_elseBlock)
2474 generator.emitJump(afterElse.get());
2475 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002476
2477 generator.emitLabel(beforeElse.get());
2478
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002479 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002480 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002481 generator.emitNodeInTailPosition(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002482 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002483
2484 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002485 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2486 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002487}
2488
2489// ------------------------------ DoWhileNode ----------------------------------
2490
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002491void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002492{
oliver@apple.com6a976452013-03-11 21:02:39 +00002493 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002494
2495 RefPtr<Label> topOfLoop = generator.newLabel();
2496 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002497 generator.emitLoopHint();
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002498
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002499 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002500
2501 generator.emitLabel(scope->continueTarget());
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002502 generator.emitDebugHook(m_expr, WillExecuteStatement);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002503 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002504
2505 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002506}
2507
2508// ------------------------------ WhileNode ------------------------------------
2509
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002510void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002511{
oliver@apple.com6a976452013-03-11 21:02:39 +00002512 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002513 RefPtr<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002514
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002515 generator.emitDebugHook(m_expr, WillExecuteStatement);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002516 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002517
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002518 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002519 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002520
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002521 generator.emitProfileControlFlow(m_statement->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002522 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002523
2524 generator.emitLabel(scope->continueTarget());
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002525 generator.emitDebugHook(m_expr, WillExecuteStatement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002526
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002527 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002528
2529 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002530
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002531 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002532}
2533
2534// ------------------------------ ForNode --------------------------------------
2535
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002536void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002537{
oliver@apple.com6a976452013-03-11 21:02:39 +00002538 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002539
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002540 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002541 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002542
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002543 if (m_expr1 || m_expr2) {
2544 ExpressionNode* firstExpr = m_expr1 ? m_expr1 : m_expr2;
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002545 generator.emitDebugHook(firstExpr, WillExecuteStatement);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002546 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002547
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002548 if (m_expr1) {
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002549 generator.emitDebugHook(m_expr1, WillExecuteExpression);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002550 generator.emitNode(generator.ignoredResult(), m_expr1);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002551 }
2552
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002553 RefPtr<Label> topOfLoop = generator.newLabel();
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002554 if (m_expr2) {
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002555 generator.emitDebugHook(m_expr2, WillExecuteExpression);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002556 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002557 }
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002558
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002559 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002560 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002561 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002562
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002563 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002564
2565 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002566 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002567 if (m_expr3) {
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002568 generator.emitDebugHook(m_expr3, WillExecuteStatement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002569 generator.emitNode(generator.ignoredResult(), m_expr3);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002570 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002571
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002572 if (m_expr2) {
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002573 generator.emitDebugHook(m_expr2, WillExecuteStatement);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002574 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002575 } else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002576 generator.emitJump(topOfLoop.get());
2577
2578 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002579 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002580 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002581}
2582
2583// ------------------------------ ForInNode ------------------------------------
2584
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002585RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002586{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002587 if (m_lexpr->isResolveNode()) {
2588 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002589 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002590 }
2591
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002592 if (m_lexpr->isDestructuringNode()) {
2593 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002594 auto binding = assignNode->bindings();
2595 if (!binding->isBindingNode())
2596 return nullptr;
2597
2598 auto simpleBinding = static_cast<BindingNode*>(binding);
2599 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002600 Variable var = generator.variable(ident);
2601 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002602 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002603 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002604 }
2605
2606 return nullptr;
2607}
2608
2609void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2610{
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002611 auto lambdaEmitResolveVariable = [&](const Identifier& ident)
2612 {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002613 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002614 if (RegisterID* local = var.local()) {
2615 if (var.isReadOnly())
2616 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002617 generator.emitMove(local, propertyName);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002618 } else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002619 if (generator.isStrictMode())
2620 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002621 if (var.isReadOnly())
2622 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002623 RegisterID* scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002624 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002625 generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002626 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002627 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002628 };
2629
2630 if (m_lexpr->isResolveNode()) {
2631 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2632 lambdaEmitResolveVariable(ident);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002633 return;
2634 }
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002635
2636 if (m_lexpr->isAssignResolveNode()) {
2637 const Identifier& ident = static_cast<AssignResolveNode*>(m_lexpr)->identifier();
2638 lambdaEmitResolveVariable(ident);
2639 return;
2640 }
2641
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002642 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002643 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2644 const Identifier& ident = assignNode->identifier();
sbarati@apple.com23315d62016-05-09 20:17:23 +00002645 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002646 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002647 if (assignNode->base()->isSuperNode()) {
2648 RefPtr<RegisterID> thisValue = generator.ensureThis();
2649 generator.emitPutById(base.get(), thisValue.get(), ident, propertyName);
2650 } else
2651 generator.emitPutById(base.get(), ident, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002652 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002653 return;
2654 }
2655 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002656 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002657 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002658 RefPtr<RegisterID> subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002659 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002660 if (assignNode->base()->isSuperNode()) {
2661 RefPtr<RegisterID> thisValue = generator.ensureThis();
2662 generator.emitPutByVal(base.get(), thisValue.get(), subscript.get(), propertyName);
2663 } else
2664 generator.emitPutByVal(base.get(), subscript.get(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002665 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002666 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002667 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002668
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002669 if (m_lexpr->isDestructuringNode()) {
2670 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002671 auto binding = assignNode->bindings();
2672 if (!binding->isBindingNode()) {
2673 assignNode->bindings()->bindValue(generator, propertyName);
2674 return;
2675 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002676
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002677 auto simpleBinding = static_cast<BindingNode*>(binding);
2678 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002679 Variable var = generator.variable(ident);
2680 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002681 assignNode->bindings()->bindValue(generator, propertyName);
2682 return;
2683 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002684 generator.emitMove(var.local(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002685 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002686 return;
2687 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002688
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002689 RELEASE_ASSERT_NOT_REACHED();
2690}
2691
commit-queue@webkit.org3057eed2016-09-21 22:52:37 +00002692void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002693{
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002694 if (!m_lexpr->isAssignResolveNode() && !m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002695 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002696 return;
2697 }
2698
2699 RefPtr<Label> end = generator.newLabel();
2700
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002701 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002702 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002703
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002704 generator.emitDebugHook(m_expr, WillExecuteStatement);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002705
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002706 if (m_lexpr->isAssignResolveNode())
2707 generator.emitNode(generator.ignoredResult(), m_lexpr);
2708
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002709 RefPtr<RegisterID> base = generator.newTemporary();
2710 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002711 RefPtr<RegisterID> enumerator;
gskachkov@gmail.comad01d6b2016-08-24 13:35:38 +00002712
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002713 generator.emitNode(base.get(), m_expr);
2714 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002715 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002716
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002717 int profilerStartOffset = m_statement->startOffset();
2718 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002719
2720 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2721
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002722 // Indexed property loop.
2723 {
2724 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2725 RefPtr<Label> loopStart = generator.newLabel();
2726 RefPtr<Label> loopEnd = generator.newLabel();
2727
msaboff@apple.comb644c252015-03-24 10:05:21 +00002728 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002729 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2730 RefPtr<RegisterID> propertyName = generator.newTemporary();
2731
2732 generator.emitLabel(loopStart.get());
2733 generator.emitLoopHint();
2734
2735 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2736 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2737 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
2738 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2739
2740 generator.emitToIndexString(propertyName.get(), i.get());
2741 this->emitLoopHeader(generator, propertyName.get());
2742
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002743 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002744
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002745 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002746 generator.emitNode(dst, m_statement);
2747 generator.popIndexedForInScope(local.get());
2748
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002749 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002750
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002751 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002752 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002753 generator.emitInc(i.get());
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002754 generator.emitDebugHook(m_expr, WillExecuteStatement);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002755 generator.emitJump(loopStart.get());
2756
2757 generator.emitLabel(scope->breakTarget());
2758 generator.emitJump(end.get());
2759 generator.emitLabel(loopEnd.get());
2760 }
2761
2762 // Structure property loop.
2763 {
2764 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2765 RefPtr<Label> loopStart = generator.newLabel();
2766 RefPtr<Label> loopEnd = generator.newLabel();
2767
msaboff@apple.comb644c252015-03-24 10:05:21 +00002768 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002769 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002770 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002771
2772 generator.emitLabel(loopStart.get());
2773 generator.emitLoopHint();
2774
2775 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2776 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002777 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002778 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2779
2780 this->emitLoopHeader(generator, propertyName.get());
2781
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002782 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002783
msaboff@apple.comb644c252015-03-24 10:05:21 +00002784 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002785 generator.emitNode(dst, m_statement);
2786 generator.popStructureForInScope(local.get());
2787
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002788 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002789
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002790 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002791 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002792 generator.emitInc(enumeratorIndex.get());
2793 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002794 generator.emitDebugHook(m_expr, WillExecuteStatement);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002795 generator.emitJump(loopStart.get());
2796
2797 generator.emitLabel(scope->breakTarget());
2798 generator.emitJump(end.get());
2799 generator.emitLabel(loopEnd.get());
2800 }
2801
2802 // Generic property loop.
2803 {
2804 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2805 RefPtr<Label> loopStart = generator.newLabel();
2806 RefPtr<Label> loopEnd = generator.newLabel();
2807
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002808 RefPtr<RegisterID> propertyName = generator.newTemporary();
2809
msaboff@apple.comb644c252015-03-24 10:05:21 +00002810 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002811
2812 generator.emitLabel(loopStart.get());
2813 generator.emitLoopHint();
2814
msaboff@apple.comb644c252015-03-24 10:05:21 +00002815 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2816 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2817
2818 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
2819 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2820
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002821 this->emitLoopHeader(generator, propertyName.get());
2822
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002823 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002824
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002825 generator.emitNode(dst, m_statement);
2826
2827 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002828 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002829 generator.emitInc(enumeratorIndex.get());
2830 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002831 generator.emitDebugHook(m_expr, WillExecuteStatement);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002832 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002833
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002834 generator.emitLabel(scope->breakTarget());
2835 generator.emitJump(end.get());
2836 generator.emitLabel(loopEnd.get());
2837 }
2838
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002839 generator.emitLabel(end.get());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002840 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002841 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002842}
2843
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002844// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002845void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2846{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002847 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002848 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002849 return;
2850 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002851
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002852 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002853 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002854 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002855 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002856 if (m_lexpr->isResolveNode()) {
2857 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002858 Variable var = generator.variable(ident);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002859 if (RegisterID* local = var.local()) {
2860 if (var.isReadOnly())
2861 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002862 generator.emitMove(local, value);
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002863 } else {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002864 if (generator.isStrictMode())
2865 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.orge7874f42016-08-17 23:57:03 +00002866 if (var.isReadOnly())
2867 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002868 RegisterID* scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002869 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002870 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002871 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002872 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00002873 } else if (m_lexpr->isDotAccessorNode()) {
2874 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2875 const Identifier& ident = assignNode->identifier();
2876 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2877
2878 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002879 if (assignNode->base()->isSuperNode()) {
2880 RefPtr<RegisterID> thisValue = generator.ensureThis();
2881 generator.emitPutById(base.get(), thisValue.get(), ident, value);
2882 } else
2883 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002884 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002885 } else if (m_lexpr->isBracketAccessorNode()) {
2886 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
2887 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2888 RegisterID* subscript = generator.emitNode(assignNode->subscript());
2889
2890 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002891 if (assignNode->base()->isSuperNode()) {
2892 RefPtr<RegisterID> thisValue = generator.ensureThis();
2893 generator.emitPutByVal(base.get(), thisValue.get(), subscript, value);
2894 } else
2895 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002896 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002897 } else {
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002898 ASSERT(m_lexpr->isDestructuringNode());
2899 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00002900 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002901 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002902 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002903 generator.emitNode(dst, m_statement);
2904 };
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002905 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
2906 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002907 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002908}
2909
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002910// ------------------------------ ContinueNode ---------------------------------
2911
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002912Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
2913{
2914 if (generator.shouldEmitDebugHooks())
2915 return 0;
2916
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002917 LabelScopePtr scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002918 ASSERT(scope);
2919
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002920 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002921 return 0;
2922
2923 return scope->continueTarget();
2924}
2925
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002926void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002927{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002928 generator.emitDebugHook(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002929
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002930 LabelScopePtr scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002931 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002932
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002933 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002934 generator.emitJump(scope->continueTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002935
2936 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002937}
2938
2939// ------------------------------ BreakNode ------------------------------------
2940
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002941Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
2942{
2943 if (generator.shouldEmitDebugHooks())
2944 return 0;
2945
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002946 LabelScopePtr scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002947 ASSERT(scope);
2948
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002949 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002950 return 0;
2951
2952 return scope->breakTarget();
2953}
2954
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002955void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002956{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002957 generator.emitDebugHook(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002958
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002959 LabelScopePtr scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002960 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002961
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002962 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002963 generator.emitJump(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002964
2965 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002966}
2967
2968// ------------------------------ ReturnNode -----------------------------------
2969
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002970void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002971{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00002972 generator.emitDebugHook(this);
2973
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002974 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002975
2976 if (dst == generator.ignoredResult())
2977 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002978
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002979 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002980
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002981 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
saambarati1@gmail.com88b7e5b2015-08-05 21:45:20 +00002982 if (generator.isInFinallyBlock()) {
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002983 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002984 generator.emitPopScopes(generator.scopeRegister(), 0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002985 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002986
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00002987 generator.emitWillLeaveCallFrameDebugHook();
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002988 generator.emitReturn(returnRegister.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002989 generator.emitProfileControlFlow(endOffset());
2990 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
2991 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
2992 if (generator.vm()->controlFlowProfiler())
2993 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002994}
2995
2996// ------------------------------ WithNode -------------------------------------
2997
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002998void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002999{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00003000 generator.emitDebugHook(m_expr, WillExecuteStatement);
ggaren@apple.com170d6f22012-09-02 21:27:23 +00003001
3002 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003003 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003004 generator.emitPushWithScope(scope.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003005 generator.emitNodeInTailPosition(dst, m_statement);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00003006 generator.emitPopWithScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003007}
3008
3009// ------------------------------ CaseClauseNode --------------------------------
3010
3011inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3012{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003013 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003014 if (!m_statements)
3015 return;
3016 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003017}
3018
3019// ------------------------------ CaseBlockNode --------------------------------
3020
3021enum SwitchKind {
3022 SwitchUnset = 0,
3023 SwitchNumber = 1,
3024 SwitchString = 2,
3025 SwitchNeither = 3
3026};
3027
3028static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
3029{
3030 for (; list; list = list->getNext()) {
3031 ExpressionNode* clauseExpression = list->getClause()->expr();
3032 literalVector.append(clauseExpression);
3033 if (clauseExpression->isNumber()) {
3034 double value = static_cast<NumberNode*>(clauseExpression)->value();
3035 int32_t intVal = static_cast<int32_t>(value);
3036 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
3037 typeForTable = SwitchNeither;
3038 break;
3039 }
3040 if (intVal < min_num)
3041 min_num = intVal;
3042 if (intVal > max_num)
3043 max_num = intVal;
3044 typeForTable = SwitchNumber;
3045 continue;
3046 }
3047 if (clauseExpression->isString()) {
3048 if (typeForTable & ~SwitchString) {
3049 typeForTable = SwitchNeither;
3050 break;
3051 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00003052 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00003053 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00003054 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003055 if (intVal < min_num)
3056 min_num = intVal;
3057 if (intVal > max_num)
3058 max_num = intVal;
3059 }
3060 typeForTable = SwitchString;
3061 continue;
3062 }
3063 typeForTable = SwitchNeither;
3064 break;
3065 }
3066}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003067
3068static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003069{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003070 size_t length = 0;
3071 for (ClauseListNode* node = list1; node; node = node->getNext())
3072 ++length;
3073 for (ClauseListNode* node = list2; node; node = node->getNext())
3074 ++length;
3075 return length;
3076}
3077
3078SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
3079{
3080 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
3081 return SwitchInfo::SwitchNone;
3082
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003083 SwitchKind typeForTable = SwitchUnset;
3084 bool singleCharacterSwitch = true;
3085
3086 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3087 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
3088
3089 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
3090 return SwitchInfo::SwitchNone;
3091
3092 if (typeForTable == SwitchNumber) {
3093 int32_t range = max_num - min_num;
3094 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3095 return SwitchInfo::SwitchImmediate;
3096 return SwitchInfo::SwitchNone;
3097 }
3098
3099 ASSERT(typeForTable == SwitchString);
3100
3101 if (singleCharacterSwitch) {
3102 int32_t range = max_num - min_num;
3103 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
3104 return SwitchInfo::SwitchCharacter;
3105 }
3106
3107 return SwitchInfo::SwitchString;
3108}
3109
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003110void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003111{
3112 RefPtr<Label> defaultLabel;
3113 Vector<RefPtr<Label>, 8> labelVector;
3114 Vector<ExpressionNode*, 8> literalVector;
3115 int32_t min_num = std::numeric_limits<int32_t>::max();
3116 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003117 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003118
3119 if (switchType != SwitchInfo::SwitchNone) {
3120 // Prepare the various labels
3121 for (uint32_t i = 0; i < literalVector.size(); i++)
3122 labelVector.append(generator.newLabel());
3123 defaultLabel = generator.newLabel();
3124 generator.beginSwitch(switchExpression, switchType);
3125 } else {
3126 // Setup jumps
3127 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3128 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3129 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3130 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3131 labelVector.append(generator.newLabel());
3132 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3133 }
3134
3135 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3136 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3137 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3138 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3139 labelVector.append(generator.newLabel());
3140 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3141 }
3142 defaultLabel = generator.newLabel();
3143 generator.emitJump(defaultLabel.get());
3144 }
3145
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003146 size_t i = 0;
3147 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3148 generator.emitLabel(labelVector[i++].get());
3149 list->getClause()->emitBytecode(generator, dst);
3150 }
3151
3152 if (m_defaultClause) {
3153 generator.emitLabel(defaultLabel.get());
3154 m_defaultClause->emitBytecode(generator, dst);
3155 }
3156
3157 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3158 generator.emitLabel(labelVector[i++].get());
3159 list->getClause()->emitBytecode(generator, dst);
3160 }
3161 if (!m_defaultClause)
3162 generator.emitLabel(defaultLabel.get());
3163
3164 ASSERT(i == labelVector.size());
3165 if (switchType != SwitchInfo::SwitchNone) {
3166 ASSERT(labelVector.size() == literalVector.size());
3167 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
3168 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003169}
3170
3171// ------------------------------ SwitchNode -----------------------------------
3172
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003173void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003174{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00003175 generator.emitDebugHook(m_expr, WillExecuteStatement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003176
oliver@apple.com6a976452013-03-11 21:02:39 +00003177 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003178
3179 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003180
sbarati@apple.combdbba812015-12-19 00:19:41 +00003181 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::DoNotOptimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003182 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003183 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003184
3185 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003186 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003187}
3188
3189// ------------------------------ LabelNode ------------------------------------
3190
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003191void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003192{
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003193 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003194
oliver@apple.com6a976452013-03-11 21:02:39 +00003195 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00003196 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003197
3198 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003199}
3200
3201// ------------------------------ ThrowNode ------------------------------------
3202
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003203void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003204{
joepeck@webkit.orgf26f3b12016-09-30 19:22:50 +00003205 generator.emitDebugHook(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003206
3207 if (dst == generator.ignoredResult())
3208 dst = 0;
3209 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003210 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003211 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003212
3213 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003214}
3215
3216// ------------------------------ TryNode --------------------------------------
3217
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003218void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003219{
3220 // NOTE: The catch and finally blocks must be labeled explicitly, so the
3221 // optimizer knows they may be jumped to from anywhere.
3222
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003223 ASSERT(m_catchBlock || m_finallyBlock);
3224
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003225 RefPtr<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003226 generator.emitLabel(tryStartLabel.get());
3227
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003228 if (m_finallyBlock)
3229 generator.pushFinallyContext(m_finallyBlock);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003230 TryData* tryData = generator.pushTry(tryStartLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003231
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003232 generator.emitNode(dst, m_tryBlock);
3233
3234 if (m_catchBlock) {
3235 RefPtr<Label> catchEndLabel = generator.newLabel();
3236
3237 // Normal path: jump over the catch block.
3238 generator.emitJump(catchEndLabel.get());
3239
3240 // Uncaught exception path: the catch block.
3241 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003242 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
3243 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
3244 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), here.get(), HandlerType::Catch);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003245
3246 if (m_finallyBlock) {
3247 // If the catch block throws an exception and we have a finally block, then the finally
3248 // block should "catch" that exception.
3249 tryData = generator.pushTry(here.get());
3250 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00003251
utatane.tea@gmail.com08fe3112016-01-22 04:21:36 +00003252 generator.emitPushCatchScope(m_lexicalVariables);
3253 m_catchPattern->bindValue(generator, thrownValueRegister.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003254 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003255 if (m_finallyBlock)
3256 generator.emitNode(dst, m_catchBlock);
3257 else
3258 generator.emitNodeInTailPosition(dst, m_catchBlock);
msaboff@apple.com78461ac2016-06-02 04:07:14 +00003259 generator.emitLoad(thrownValueRegister.get(), jsUndefined());
sbarati@apple.com62be0b02015-09-19 15:36:46 +00003260 generator.emitPopCatchScope(m_lexicalVariables);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003261 generator.emitLabel(catchEndLabel.get());
3262 }
3263
3264 if (m_finallyBlock) {
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003265 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
3266
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003267 generator.popFinallyContext();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003268
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003269 RefPtr<Label> finallyEndLabel = generator.newLabel();
3270
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003271 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003272
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003273 // Normal path: run the finally code, and jump to the end.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003274 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003275 generator.emitNodeInTailPosition(dst, m_finallyBlock);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003276 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003277 generator.emitJump(finallyEndLabel.get());
3278
3279 // Uncaught exception path: invoke the finally block, then re-throw the exception.
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003280 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
3281 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
3282 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003283 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003284 generator.emitNodeInTailPosition(dst, m_finallyBlock);
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003285 generator.emitThrow(exceptionRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003286
3287 generator.emitLabel(finallyEndLabel.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003288 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003289 } else
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003290 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003291
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003292}
3293
3294// ------------------------------ ScopeNode -----------------------------
3295
3296inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
3297{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003298 if (!m_statements)
3299 return;
3300 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003301}
3302
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003303static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
3304{
3305 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
3306
3307 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3308 generator.emitLoad(dstRegister.get(), jsUndefined());
3309 generator.emitProfileControlFlow(scopeNode.startStartOffset());
3310 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
3311
3312 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
3313 generator.emitEnd(dstRegister.get());
3314}
3315
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003316// ------------------------------ ProgramNode -----------------------------
3317
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003318void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003319{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003320 emitProgramNodeBytecode(generator, *this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003321}
3322
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003323// ------------------------------ ModuleProgramNode --------------------
3324
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003325void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003326{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003327 emitProgramNodeBytecode(generator, *this);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003328}
3329
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003330// ------------------------------ EvalNode -----------------------------
3331
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003332void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003333{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003334 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003335
3336 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3337 generator.emitLoad(dstRegister.get(), jsUndefined());
3338 emitStatementsBytecode(generator, dstRegister.get());
3339
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003340 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003341 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003342}
3343
ggaren@apple.come7afe402015-08-10 20:24:35 +00003344// ------------------------------ FunctionNode -----------------------------
ggaren@apple.com6f851d72014-12-04 23:47:49 +00003345
3346void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003347{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00003348 if (generator.vm()->typeProfiler()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003349 for (size_t i = 0; i < m_parameters->size(); i++) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003350 // Destructuring parameters are handled in destructuring nodes.
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00003351 if (!m_parameters->at(i).first->isBindingNode())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003352 continue;
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00003353 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003354 RegisterID reg(CallFrame::argumentOffset(i));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003355 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003356 }
3357 }
3358
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003359 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003360 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003361
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003362 switch (generator.parseMode()) {
3363 case SourceParseMode::GeneratorWrapperFunctionMode: {
3364 StatementNode* singleStatement = this->singleStatement();
3365 ASSERT(singleStatement->isExprStatement());
3366 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3367 ExpressionNode* expr = exprStatement->expr();
3368 ASSERT(expr->isFuncExprNode());
3369 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003370
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003371 RefPtr<RegisterID> next = generator.newTemporary();
3372 generator.emitNode(next.get(), funcExpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003373
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003374 if (generator.superBinding() == SuperBinding::Needed) {
3375 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3376 emitPutHomeObject(generator, next.get(), homeObject.get());
3377 }
3378
3379 // FIXME: Currently, we just create an object and store generator related fields as its properties for ease.
3380 // But to make it efficient, we will introduce JSGenerator class, add opcode new_generator and use its C++ fields instead of these private properties.
3381 // https://bugs.webkit.org/show_bug.cgi?id=151545
3382
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +00003383 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().builtinNames().generatorNextPrivateName(), next.get(), PropertyNode::KnownDirect);
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003384
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +00003385 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().builtinNames().generatorThisPrivateName(), generator.thisRegister(), PropertyNode::KnownDirect);
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003386
3387 RegisterID* initialState = generator.emitLoad(nullptr, jsNumber(0));
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +00003388 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().builtinNames().generatorStatePrivateName(), initialState, PropertyNode::KnownDirect);
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003389
keith_miller@apple.com1ec869c2016-06-21 17:54:33 +00003390 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().builtinNames().generatorFramePrivateName(), generator.emitLoad(nullptr, jsNull()), PropertyNode::KnownDirect);
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003391
mark.lam@apple.comfa35e782013-11-19 21:55:16 +00003392 ASSERT(startOffset() >= lineStartOffset());
3393 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003394 generator.emitReturn(generator.generatorRegister());
3395 break;
3396 }
3397
3398 case SourceParseMode::GeneratorBodyMode: {
3399 RefPtr<Label> generatorBodyLabel = generator.newLabel();
3400 {
3401 RefPtr<RegisterID> condition = generator.newTemporary();
3402 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))));
3403 generator.emitJumpIfTrue(condition.get(), generatorBodyLabel.get());
3404
3405 RefPtr<Label> throwLabel = generator.newLabel();
3406 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))));
3407 generator.emitJumpIfTrue(condition.get(), throwLabel.get());
3408
3409 generator.emitReturn(generator.generatorValueRegister());
3410
3411 generator.emitLabel(throwLabel.get());
3412 generator.emitThrow(generator.generatorValueRegister());
3413 }
3414
3415 generator.emitLabel(generatorBodyLabel.get());
3416
3417 emitStatementsBytecode(generator, generator.ignoredResult());
3418
3419 RefPtr<Label> done = generator.newLabel();
3420 generator.emitLabel(done.get());
3421 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003422 break;
3423 }
3424
3425 default: {
3426 emitStatementsBytecode(generator, generator.ignoredResult());
3427
3428 StatementNode* singleStatement = this->singleStatement();
3429 ReturnNode* returnNode = 0;
3430
3431 // Check for a return statement at the end of a function composed of a single block.
3432 if (singleStatement && singleStatement->isBlock()) {
3433 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
3434 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
3435 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
3436 }
3437
3438 // If there is no return we must automatically insert one.
3439 if (!returnNode) {
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003440 if (generator.constructorKind() == ConstructorKind::Extends && generator.needsToUpdateArrowFunctionContext() && generator.isSuperCallUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +00003441 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
3442
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003443 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
3444 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
3445 ASSERT(startOffset() >= lineStartOffset());
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003446 generator.emitWillLeaveCallFrameDebugHook();
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003447 generator.emitReturn(r0);
3448 return;
3449 }
3450 break;
3451 }
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003452 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003453}
3454
3455// ------------------------------ FuncDeclNode ---------------------------------
3456
sbarati@apple.come86176c2016-04-07 21:01:42 +00003457void FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003458{
sbarati@apple.come86176c2016-04-07 21:01:42 +00003459 generator.hoistSloppyModeFunctionIfNecessary(metadata()->ident());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003460}
3461
3462// ------------------------------ FuncExprNode ---------------------------------
3463
3464RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3465{
3466 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3467}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003468
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00003469// ------------------------------ ArrowFuncExprNode ---------------------------------
3470
3471RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3472{
3473 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3474}
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003475
mark.lam@apple.com43137872016-03-17 14:58:57 +00003476// ------------------------------ MethodDefinitionNode ---------------------------------
3477
3478RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3479{
3480 return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
3481}
3482
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003483// ------------------------------ YieldExprNode --------------------------------
3484
3485RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3486{
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003487 if (!delegate()) {
3488 RefPtr<RegisterID> arg = nullptr;
3489 if (argument()) {
3490 arg = generator.newTemporary();
3491 generator.emitNode(arg.get(), argument());
3492 } else
3493 arg = generator.emitLoad(nullptr, jsUndefined());
3494 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3495 if (dst == generator.ignoredResult())
3496 return nullptr;
3497 return generator.emitMove(generator.finalDestination(dst), value.get());
3498 }
3499 RefPtr<RegisterID> arg = generator.newTemporary();
3500 generator.emitNode(arg.get(), argument());
3501 RefPtr<RegisterID> value = generator.emitDelegateYield(arg.get(), this);
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003502 if (dst == generator.ignoredResult())
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003503 return nullptr;
3504 return generator.emitMove(generator.finalDestination(dst), value.get());
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003505}
3506
caitp@igalia.com0096c962016-09-23 22:24:27 +00003507// ------------------------------ AwaitExprNode --------------------------------
3508
3509RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3510{
3511 RefPtr<RegisterID> arg = generator.newTemporary();
3512 generator.emitNode(arg.get(), argument());
3513 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3514 if (dst == generator.ignoredResult())
3515 return nullptr;
3516 return generator.emitMove(generator.finalDestination(dst), value.get());
3517}
3518
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003519// ------------------------------ ClassDeclNode ---------------------------------
3520
3521void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3522{
3523 generator.emitNode(dst, m_classDeclaration);
3524}
3525
3526// ------------------------------ ClassExprNode ---------------------------------
3527
3528RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3529{
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003530 if (!m_name.isNull())
sbarati@apple.combdbba812015-12-19 00:19:41 +00003531 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003532
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003533 RefPtr<RegisterID> superclass;
3534 if (m_classHeritage) {
3535 superclass = generator.newTemporary();
3536 generator.emitNode(superclass.get(), m_classHeritage);
3537 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003538
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003539 RefPtr<RegisterID> constructor;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003540
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003541 // FIXME: Make the prototype non-configurable & non-writable.
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003542 if (m_constructorExpression) {
3543 ASSERT(m_constructorExpression->isFuncExprNode());
3544 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata();
3545 metadata->setEcmaName(ecmaName());
3546 metadata->setClassSource(m_classSource);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003547 constructor = generator.emitNode(dst, m_constructorExpression);
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003548 if (m_classHeritage) {
3549 RefPtr<RegisterID> isDerivedConstructor = generator.newTemporary();
3550 generator.emitUnaryOp(op_not, isDerivedConstructor.get(),
3551 generator.emitUnaryOp(op_eq_null, isDerivedConstructor.get(), superclass.get()));
3552 generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), isDerivedConstructor.get(), PropertyNode::Unknown);
3553 }
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003554 } else {
sbarati@apple.com8a1620b62016-08-03 01:28:16 +00003555 if (m_classHeritage) {
3556 constructor = generator.finalDestination(dst);
3557 RefPtr<RegisterID> tempRegister = generator.newTemporary();
3558 RefPtr<Label> superclassIsNullLabel = generator.newLabel();
3559 RefPtr<Label> done = generator.newLabel();
3560
3561 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3562 generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Extends, m_name, ecmaName(), m_classSource);
3563 generator.emitLoad(tempRegister.get(), jsBoolean(true));
3564 generator.emitJump(done.get());
3565 generator.emitLabel(superclassIsNullLabel.get());
3566 generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3567 generator.emitLoad(tempRegister.get(), jsBoolean(false));
3568 generator.emitLabel(done.get());
3569 generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), tempRegister.get(), PropertyNode::Unknown);
3570 } else {
3571 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
3572 ConstructorKind::Base, m_name, ecmaName(), m_classSource);
3573 }
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003574 }
3575
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003576 const auto& propertyNames = generator.propertyNames();
3577 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003578
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003579 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003580 RefPtr<RegisterID> protoParent = generator.newTemporary();
3581 generator.emitLoad(protoParent.get(), jsNull());
3582
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003583 RefPtr<RegisterID> tempRegister = generator.newTemporary();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003584
3585 // FIXME: Throw TypeError if it's a generator function.
3586 RefPtr<Label> superclassIsUndefinedLabel = generator.newLabel();
3587 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
3588
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003589 RefPtr<Label> superclassIsNullLabel = generator.newLabel();
3590 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3591
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003592 RefPtr<Label> superclassIsObjectLabel = generator.newLabel();
3593 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003594 generator.emitLabel(superclassIsUndefinedLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003595 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3596 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003597 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
3598
3599 RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
3600 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
keith_miller@apple.com02373132016-01-14 20:45:48 +00003601 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_function, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
3602 generator.emitThrowTypeError(ASCIILiteral("The value of the superclass's prototype property is not an object."));
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003603 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
3604
3605 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003606 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003607 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
3608
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003609 emitPutHomeObject(generator, constructor.get(), prototype.get());
3610 }
3611
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003612 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(nullptr, propertyNames.constructor);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003613 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003614 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003615
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003616 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(nullptr, propertyNames.prototype);
3617 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003618
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003619 if (m_staticMethods)
3620 generator.emitNode(constructor.get(), m_staticMethods);
3621
3622 if (m_instanceMethods)
3623 generator.emitNode(prototype.get(), m_instanceMethods);
3624
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003625 if (!m_name.isNull()) {
3626 Variable classNameVar = generator.variable(m_name);
3627 RELEASE_ASSERT(classNameVar.isResolved());
3628 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
sbarati@apple.come67fd782016-04-19 01:38:30 +00003629 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003630 generator.popLexicalScope(this);
3631 }
3632
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003633 return generator.moveToDestinationIfNeeded(dst, constructor.get());
3634}
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003635
3636// ------------------------------ ImportDeclarationNode -----------------------
3637
3638void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3639{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003640 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003641}
3642
3643// ------------------------------ ExportAllDeclarationNode --------------------
3644
3645void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3646{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003647 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003648}
3649
3650// ------------------------------ ExportDefaultDeclarationNode ----------------
3651
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003652void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003653{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003654 ASSERT(m_declaration);
3655 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003656}
3657
3658// ------------------------------ ExportLocalDeclarationNode ------------------
3659
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003660void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003661{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003662 ASSERT(m_declaration);
3663 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003664}
3665
3666// ------------------------------ ExportNamedDeclarationNode ------------------
3667
3668void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3669{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003670 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003671}
3672
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003673// ------------------------------ DestructuringAssignmentNode -----------------
3674RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
oliver@apple.comd055db62013-10-02 19:11:04 +00003675{
3676 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
3677 return result;
3678 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
3679 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00003680 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003681 return generator.moveToDestinationIfNeeded(dst, initializer.get());
3682}
3683
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003684static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
3685{
3686 ASSERT(defaultValue);
3687 RefPtr<Label> isNotUndefined = generator.newLabel();
3688 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
3689 generator.emitNode(maybeUndefined, defaultValue);
3690 generator.emitLabel(isNotUndefined.get());
3691}
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003692
oliver@apple.com47784d62013-10-25 21:31:36 +00003693void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003694{
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003695 RefPtr<RegisterID> iterator = generator.newTemporary();
3696 {
3697 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
3698 CallArguments args(generator, nullptr);
3699 generator.emitMove(args.thisRegister(), rhs);
joepeck@webkit.orgbb70ac62016-09-30 19:22:37 +00003700 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003701 }
3702
utatane.tea@gmail.coma5c94332015-06-23 00:51:44 +00003703 if (m_targetPatterns.isEmpty()) {
3704 generator.emitIteratorClose(iterator.get(), this);
3705 return;
3706 }
3707
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003708 RefPtr<RegisterID> done;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003709 for (auto& target : m_targetPatterns) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003710 switch (target.bindingType) {
3711 case BindingType::Elision:
3712 case BindingType::Element: {
3713 RefPtr<Label> iterationSkipped = generator.newLabel();
3714 if (!done)
3715 done = generator.newTemporary();
3716 else
3717 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003718
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003719 RefPtr<RegisterID> value = generator.newTemporary();
3720 generator.emitIteratorNext(value.get(), iterator.get(), this);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003721 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003722 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
3723 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003724
3725 {
3726 RefPtr<Label> valueIsSet = generator.newLabel();
3727 generator.emitJump(valueIsSet.get());
3728 generator.emitLabel(iterationSkipped.get());
3729 generator.emitLoad(value.get(), jsUndefined());
3730 generator.emitLabel(valueIsSet.get());
3731 }
3732
3733 if (target.bindingType == BindingType::Element) {
3734 if (target.defaultValue)
3735 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
3736 target.pattern->bindValue(generator, value.get());
3737 }
3738 break;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003739 }
3740
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003741 case BindingType::RestElement: {
3742 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
3743
3744 RefPtr<Label> iterationDone = generator.newLabel();
3745 if (!done)
3746 done = generator.newTemporary();
3747 else
3748 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3749
3750 RefPtr<RegisterID> index = generator.newTemporary();
3751 generator.emitLoad(index.get(), jsNumber(0));
3752 RefPtr<Label> loopStart = generator.newLabel();
3753 generator.emitLabel(loopStart.get());
3754
3755 RefPtr<RegisterID> value = generator.newTemporary();
3756 generator.emitIteratorNext(value.get(), iterator.get(), this);
3757 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
3758 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3759 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
3760
3761 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
3762 generator.emitInc(index.get());
3763 generator.emitJump(loopStart.get());
3764
3765 generator.emitLabel(iterationDone.get());
3766 target.pattern->bindValue(generator, array.get());
3767 break;
3768 }
3769 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003770 }
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003771
3772 RefPtr<Label> iteratorClosed = generator.newLabel();
3773 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
3774 generator.emitIteratorClose(iterator.get(), this);
3775 generator.emitLabel(iteratorClosed.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003776}
3777
3778RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
3779{
oliver@apple.comd055db62013-10-02 19:11:04 +00003780 if (!rhs->isSimpleArray())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003781 return nullptr;
3782
3783 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
3784 Vector<ExpressionNode*> elements;
3785 for (; elementNodes; elementNodes = elementNodes->next()) {
3786 ExpressionNode* value = elementNodes->value();
3787 if (value->isSpreadExpression())
3788 return nullptr;
3789 elements.append(value);
3790 }
oliver@apple.com47784d62013-10-25 21:31:36 +00003791
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003792 RefPtr<RegisterID> resultRegister;
3793 if (dst && dst != generator.ignoredResult())
3794 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00003795 if (m_targetPatterns.size() != elements.size())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003796 return nullptr;
oliver@apple.comd055db62013-10-02 19:11:04 +00003797 Vector<RefPtr<RegisterID>> registers;
3798 registers.reserveCapacity(m_targetPatterns.size());
3799 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3800 registers.uncheckedAppend(generator.newTemporary());
3801 generator.emitNode(registers.last().get(), elements[i]);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003802 if (m_targetPatterns[i].defaultValue)
3803 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003804 if (resultRegister)
3805 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003806 }
3807
3808 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003809 if (m_targetPatterns[i].pattern)
3810 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003811 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003812 if (resultRegister)
3813 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00003814 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00003815}
3816
3817void ArrayPatternNode::toString(StringBuilder& builder) const
3818{
3819 builder.append('[');
3820 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003821 const auto& target = m_targetPatterns[i];
3822
3823 switch (target.bindingType) {
3824 case BindingType::Elision:
oliver@apple.comd055db62013-10-02 19:11:04 +00003825 builder.append(',');
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003826 break;
3827
3828 case BindingType::Element:
3829 target.pattern->toString(builder);
3830 if (i < m_targetPatterns.size() - 1)
3831 builder.append(',');
3832 break;
3833
3834 case BindingType::RestElement:
commit-queue@webkit.org57101852016-08-12 00:33:47 +00003835 builder.appendLiteral("...");
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003836 target.pattern->toString(builder);
3837 break;
oliver@apple.comd055db62013-10-02 19:11:04 +00003838 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003839 }
3840 builder.append(']');
3841}
3842
3843void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3844{
3845 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.comc497d152015-07-17 18:48:30 +00003846 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
oliver@apple.comd055db62013-10-02 19:11:04 +00003847 node->collectBoundIdentifiers(identifiers);
3848 }
3849}
3850
3851void ObjectPatternNode::toString(StringBuilder& builder) const
3852{
3853 builder.append('{');
3854 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003855 if (m_targetPatterns[i].wasString)
akling@apple.coma9904fb2015-05-08 08:44:23 +00003856 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003857 else
oliver@apple.comd055db62013-10-02 19:11:04 +00003858 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00003859 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00003860 m_targetPatterns[i].pattern->toString(builder);
3861 if (i < m_targetPatterns.size() - 1)
3862 builder.append(',');
3863 }
3864 builder.append('}');
3865}
3866
oliver@apple.com47784d62013-10-25 21:31:36 +00003867void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003868{
commit-queue@webkit.org4d3e0c22015-12-01 20:11:20 +00003869 generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
oliver@apple.comd055db62013-10-02 19:11:04 +00003870 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3871 auto& target = m_targetPatterns[i];
3872 RefPtr<RegisterID> temp = generator.newTemporary();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00003873 if (!target.propertyExpression) {
3874 // Should not emit get_by_id for indexed ones.
3875 Optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
3876 if (!optionalIndex)
3877 generator.emitGetById(temp.get(), rhs, target.propertyName);
3878 else {
utatane.tea@gmail.comf7db5592016-10-04 19:31:24 +00003879 RefPtr<RegisterID> index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00003880 generator.emitGetByVal(temp.get(), rhs, index.get());
3881 }
3882 } else {
commit-queue@webkit.org38980282015-11-25 01:43:14 +00003883 RefPtr<RegisterID> propertyName = generator.emitNode(target.propertyExpression);
3884 generator.emitGetByVal(temp.get(), rhs, propertyName.get());
3885 }
3886
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003887 if (target.defaultValue)
3888 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
oliver@apple.com47784d62013-10-25 21:31:36 +00003889 target.pattern->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003890 }
3891}
3892
3893void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3894{
3895 for (size_t i = 0; i < m_targetPatterns.size(); i++)
3896 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
3897}
3898
oliver@apple.com47784d62013-10-25 21:31:36 +00003899void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003900{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003901 Variable var = generator.variable(m_boundProperty);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003902 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003903 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003904 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3905 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003906 if (isReadOnly) {
3907 generator.emitReadOnlyExceptionIfNeeded(var);
3908 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00003909 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003910 generator.emitMove(local, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003911 generator.emitProfileType(local, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003912 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003913 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003914 return;
3915 }
3916 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003917 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003918 RegisterID* scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003919 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003920 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3921 generator.emitTDZCheckIfNecessary(var, nullptr, scope);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003922 if (isReadOnly) {
3923 generator.emitReadOnlyExceptionIfNeeded(var);
3924 return;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003925 }
sbarati@apple.come67fd782016-04-19 01:38:30 +00003926 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003927 generator.emitProfileType(value, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003928 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003929 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003930 return;
3931}
3932
3933void BindingNode::toString(StringBuilder& builder) const
3934{
3935 builder.append(m_boundProperty.string());
3936}
3937
3938void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3939{
3940 identifiers.append(m_boundProperty);
3941}
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003942
3943void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
3944{
3945}
3946
3947void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
3948{
3949 if (m_assignmentTarget->isResolveNode()) {
3950 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
3951 Variable var = generator.variable(lhs->identifier());
3952 bool isReadOnly = var.isReadOnly();
3953 if (RegisterID* local = var.local()) {
3954 generator.emitTDZCheckIfNecessary(var, local, nullptr);
3955
3956 if (isReadOnly)
3957 generator.emitReadOnlyExceptionIfNeeded(var);
3958 else {
3959 generator.invalidateForInContextForLocal(local);
3960 generator.moveToDestinationIfNeeded(local, value);
3961 generator.emitProfileType(local, divotStart(), divotEnd());
3962 }
3963 return;
3964 }
3965 if (generator.isStrictMode())
3966 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3967 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
3968 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
3969 if (isReadOnly) {
3970 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
3971 if (threwException)
3972 return;
3973 }
3974 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3975 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00003976 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003977 generator.emitProfileType(value, var, divotStart(), divotEnd());
3978 }
3979 } else if (m_assignmentTarget->isDotAccessorNode()) {
3980 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
3981 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
3982 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003983 if (lhs->base()->isSuperNode()) {
3984 RefPtr<RegisterID> thisValue = generator.ensureThis();
3985 generator.emitPutById(base.get(), thisValue.get(), lhs->identifier(), value);
3986 } else
3987 generator.emitPutById(base.get(), lhs->identifier(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003988 generator.emitProfileType(value, divotStart(), divotEnd());
3989 } else if (m_assignmentTarget->isBracketAccessorNode()) {
3990 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
3991 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
3992 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(lhs->subscript(), true, false);
3993 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003994 if (lhs->base()->isSuperNode()) {
3995 RefPtr<RegisterID> thisValue = generator.ensureThis();
3996 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
3997 } else
3998 generator.emitPutByVal(base.get(), property.get(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003999 generator.emitProfileType(value, divotStart(), divotEnd());
4000 }
4001}
4002
4003void AssignmentElementNode::toString(StringBuilder& builder) const
4004{
4005 if (m_assignmentTarget->isResolveNode())
4006 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
4007}
4008
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004009void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
4010{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004011 m_pattern->collectBoundIdentifiers(identifiers);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004012}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004013
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004014void RestParameterNode::toString(StringBuilder& builder) const
4015{
commit-queue@webkit.org57101852016-08-12 00:33:47 +00004016 builder.appendLiteral("...");
sbarati@apple.com6a686122016-08-03 07:50:40 +00004017 m_pattern->toString(builder);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004018}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004019
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004020void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
4021{
4022 RELEASE_ASSERT_NOT_REACHED();
4023}
sbarati@apple.com6a686122016-08-03 07:50:40 +00004024
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004025void RestParameterNode::emit(BytecodeGenerator& generator)
4026{
sbarati@apple.com6a686122016-08-03 07:50:40 +00004027 RefPtr<RegisterID> temp = generator.newTemporary();
4028 generator.emitRestParameter(temp.get(), m_numParametersToSkip);
4029 m_pattern->bindValue(generator, temp.get());
sbarati@apple.comc0722da2015-11-20 02:37:47 +00004030}
4031
4032
oliver@apple.com72f8a822013-10-17 01:02:34 +00004033RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
4034{
4035 RELEASE_ASSERT_NOT_REACHED();
4036 return 0;
4037}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00004038
4039} // namespace JSC