blob: 8abb458e1272d18fcc175e99c51c2bd4d6df7155 [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"
34#include "Debugger.h"
35#include "JIT.h"
36#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"
oliver@apple.comd055db62013-10-02 19:11:04 +000039#include "JSONObject.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000040#include "LabelScope.h"
41#include "Lexer.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000042#include "JSCInlines.h"
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +000043#include "JSTemplateRegistryKey.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000044#include "Parser.h"
45#include "PropertyNameArray.h"
zherczeg@webkit.org17dc93a2010-06-22 19:16:57 +000046#include "RegExpCache.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000047#include "RegExpObject.h"
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +000048#include "StackAlignment.h"
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +000049#include "TemplateRegistryKey.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000050#include <wtf/Assertions.h>
51#include <wtf/RefCountedLeakCounter.h>
52#include <wtf/Threading.h>
53
54using namespace WTF;
55
56namespace JSC {
57
58/*
59 Details of the emitBytecode function.
60
61 Return value: The register holding the production's value.
62 dst: An optional parameter specifying the most efficient destination at
63 which to store the production's value. The callee must honor dst.
64
65 The dst argument provides for a crude form of copy propagation. For example,
66
67 x = 1
68
69 becomes
70
71 load r[x], 1
72
73 instead of
74
75 load r0, 1
76 mov r[x], r0
77
78 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
79*/
80
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +000081void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
82{
83 RegisterID* result = generator.emitNode(this);
84 if (fallThroughMode == FallThroughMeansTrue)
85 generator.emitJumpIfFalse(result, falseTarget);
86 else
87 generator.emitJumpIfTrue(result, trueTarget);
88}
89
mjs@apple.comaed3cef2009-12-09 01:29:52 +000090// ------------------------------ ThrowableExpressionData --------------------------------
91
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000092RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000093{
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +000094 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com4920ae92010-11-12 03:06:07 +000095 generator.emitThrowReferenceError(message);
96 return generator.newTemporary();
mjs@apple.comaed3cef2009-12-09 01:29:52 +000097}
98
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000099// ------------------------------ ConstantNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000100
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000101void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000102{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000103 TriState value = jsValue(generator).pureToBoolean();
104 if (value == MixedTriState)
105 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
106 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
107 generator.emitJump(trueTarget);
108 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
109 generator.emitJump(falseTarget);
110
111 // All other cases are unconditional fall-throughs, like "if (true)".
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000112}
113
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000114RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000115{
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000116 if (dst == generator.ignoredResult())
117 return 0;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000118 return generator.emitLoad(dst, jsValue(generator));
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000119}
120
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000121JSValue StringNode::jsValue(BytecodeGenerator& generator) const
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000122{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000123 return generator.addStringConstant(m_value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000124}
125
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000126// ------------------------------ NumberNode ----------------------------------
127
128RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
129{
130 if (dst == generator.ignoredResult())
131 return nullptr;
132 return generator.emitLoad(dst, jsValue(generator), isIntegerNode() ? SourceCodeRepresentation::Integer : SourceCodeRepresentation::Double);
133}
134
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000135// ------------------------------ RegExpNode -----------------------------------
136
137RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
138{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000139 if (dst == generator.ignoredResult())
140 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000141 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 +0000142}
143
144// ------------------------------ ThisNode -------------------------------------
145
146RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
147{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000148 generator.ensureThis();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000149 if (dst == generator.ignoredResult())
150 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000151
152 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000153 static const unsigned thisLength = 4;
154 generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000155 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000156}
157
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000158// ------------------------------ SuperNode -------------------------------------
159
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000160static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000161{
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000162 if (generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {
163 RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
164 return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().homeObjectPrivateName);
165 }
166
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000167 RegisterID callee;
168 callee.setIndex(JSStack::Callee);
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000169 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
170}
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000171
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +0000172static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
173{
174 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000175 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
176}
177
sbarati@apple.com23315d62016-05-09 20:17:23 +0000178static RegisterID* emitGetSuperFunctionForConstruct(BytecodeGenerator& generator)
179{
180 if (generator.isDerivedConstructorContext())
181 return generator.emitGetById(generator.newTemporary(), generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment(), generator.propertyNames().underscoreProto);
182
183 RegisterID callee;
184 callee.setIndex(JSStack::Callee);
185 return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().underscoreProto);
186}
187
188RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
189{
190 RegisterID* result = emitSuperBaseForCallee(generator);
191 return generator.moveToDestinationIfNeeded(generator.finalDestination(dst), result);
192}
193
commit-queue@webkit.org17f99e42015-07-21 18:18:42 +0000194// ------------------------------ NewTargetNode ----------------------------------
195
196RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
197{
198 if (dst == generator.ignoredResult())
199 return nullptr;
200
201 return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
202}
203
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000204// ------------------------------ ResolveNode ----------------------------------
205
206bool ResolveNode::isPure(BytecodeGenerator& generator) const
207{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000208 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000209}
210
211RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
212{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000213 Variable var = generator.variable(m_ident);
214 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000215 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000216 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000217 return nullptr;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000218
219 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000220 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000221 }
222
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000223 JSTextPosition divot = m_start + m_ident.length();
224 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000225 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000226 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000227 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000228 generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000229 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000230 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000231}
232
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000233// ------------------------------ TemplateStringNode -----------------------------------
234
235RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
236{
237 if (dst == generator.ignoredResult())
238 return nullptr;
239 return generator.emitLoad(dst, JSValue(generator.addStringConstant(cooked())));
240}
241
242// ------------------------------ TemplateLiteralNode -----------------------------------
243
244RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
245{
246 if (!m_templateExpressions) {
247 TemplateStringNode* templateString = m_templateStrings->value();
248 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
249 return generator.emitNode(dst, templateString);
250 }
251
252 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
253
254 TemplateStringListNode* templateString = m_templateStrings;
255 TemplateExpressionListNode* templateExpression = m_templateExpressions;
256 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
257 // Evaluate TemplateString.
258 if (!templateString->value()->cooked().isEmpty()) {
259 temporaryRegisters.append(generator.newTemporary());
260 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
261 }
262
263 // Evaluate Expression.
264 temporaryRegisters.append(generator.newTemporary());
265 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
266 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
267 }
268
269 // Evaluate tail TemplateString.
270 if (!templateString->value()->cooked().isEmpty()) {
271 temporaryRegisters.append(generator.newTemporary());
272 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
273 }
274
275 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
276}
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000277
278// ------------------------------ TaggedTemplateNode -----------------------------------
279
280RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
281{
282 ExpectedFunction expectedFunction = NoExpectedFunction;
283 RefPtr<RegisterID> tag = nullptr;
284 RefPtr<RegisterID> base = nullptr;
285 if (!m_tag->isLocation()) {
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000286 tag = generator.newTemporary();
287 tag = generator.emitNode(tag.get(), m_tag);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000288 } else if (m_tag->isResolveNode()) {
289 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
290 const Identifier& identifier = resolve->identifier();
291 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
292
293 Variable var = generator.variable(identifier);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000294 if (RegisterID* local = var.local()) {
295 generator.emitTDZCheckIfNecessary(var, local, nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000296 tag = generator.emitMove(generator.newTemporary(), local);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000297 } else {
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000298 tag = generator.newTemporary();
299 base = generator.newTemporary();
300
301 JSTextPosition newDivot = divotStart() + identifier.length();
302 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
303 generator.moveToDestinationIfNeeded(base.get(), generator.emitResolveScope(base.get(), var));
304 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
sbarati@apple.com7040cea2016-05-23 20:27:28 +0000305 generator.emitTDZCheckIfNecessary(var, tag.get(), nullptr);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000306 }
307 } else if (m_tag->isBracketAccessorNode()) {
308 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000309 base = generator.newTemporary();
310 base = generator.emitNode(base.get(), bracket->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000311 RefPtr<RegisterID> property = generator.emitNode(bracket->subscript());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000312 if (bracket->base()->isSuperNode()) {
313 RefPtr<RegisterID> thisValue = generator.ensureThis();
314 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
315 } else
316 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000317 } else {
318 ASSERT(m_tag->isDotAccessorNode());
319 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000320 base = generator.newTemporary();
321 base = generator.emitNode(base.get(), dot->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000322 if (dot->base()->isSuperNode()) {
323 RefPtr<RegisterID> thisValue = generator.ensureThis();
324 tag = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), dot->identifier());
325 } else
326 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000327 }
328
329 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(generator.newTemporary(), this);
330
331 unsigned expressionsCount = 0;
332 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
333 ++expressionsCount;
334
335 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
336 if (base)
337 generator.emitMove(callArguments.thisRegister(), base.get());
338 else
339 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
340
341 unsigned argumentIndex = 0;
342 generator.emitMove(callArguments.argumentRegister(argumentIndex++), templateObject.get());
343 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
344 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
345
346 return generator.emitCall(generator.finalDestination(dst, tag.get()), tag.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
347}
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000348
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000349// ------------------------------ ArrayNode ------------------------------------
350
351RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
352{
353 // FIXME: Should we put all of this code into emitNewArray?
354
355 unsigned length = 0;
356 ElementNode* firstPutElement;
357 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000358 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000359 break;
360 ++length;
361 }
362
363 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000364 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000365
oliver@apple.coma991d692011-06-14 23:39:25 +0000366 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000367 ElementNode* n = firstPutElement;
368 for (; n; n = n->next()) {
369 if (n->value()->isSpreadExpression())
370 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000371 RegisterID* value = generator.emitNode(n->value());
372 length += n->elision();
373 generator.emitPutByIndex(array.get(), length++, value);
374 }
375
376 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000377 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000378 generator.emitPutById(array.get(), generator.propertyNames().length, value);
379 }
380
381 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000382
383handleSpread:
384 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
385 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
386 {
oliver@apple.come050d642013-10-19 00:09:28 +0000387 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000388 generator.emitInc(index.get());
389 };
390 for (; n; n = n->next()) {
391 if (n->elision())
392 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
393 if (n->value()->isSpreadExpression()) {
394 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
395 generator.emitEnumeration(spread, spread->expression(), spreader);
396 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000397 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000398 generator.emitInc(index.get());
399 }
400 }
401
402 if (m_elision) {
403 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
404 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
405 }
406 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000407}
408
409bool ArrayNode::isSimpleArray() const
410{
411 if (m_elision || m_optional)
412 return false;
413 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
414 if (ptr->elision())
415 return false;
416 }
417 return true;
418}
419
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000420ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000421{
422 ASSERT(!m_elision && !m_optional);
423 ElementNode* ptr = m_element;
424 if (!ptr)
425 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000426 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000427 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000428 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000429 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000430 ArgumentListNode* tail = head;
431 ptr = ptr->next();
432 for (; ptr; ptr = ptr->next()) {
433 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000434 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000435 }
436 return head;
437}
438
439// ------------------------------ ObjectLiteralNode ----------------------------
440
441RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
442{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000443 if (!m_list) {
444 if (dst == generator.ignoredResult())
445 return 0;
446 return generator.emitNewObject(generator.finalDestination(dst));
447 }
448 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
449 generator.emitNode(newObj.get(), m_list);
450 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000451}
452
453// ------------------------------ PropertyListNode -----------------------------
454
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000455static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
456{
457 generator.emitPutById(function, generator.propertyNames().homeObjectPrivateName, homeObject);
458}
459
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000460RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
461{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000462 // Fast case: this loop just handles regular value properties.
463 PropertyListNode* p = this;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000464 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000465 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000466
467 // Were there any get/set properties?
468 if (p) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000469 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
470 // a computed property, just emit everything as that may override previous values.
471 bool hasComputedProperty = false;
472
barraclough@apple.com09a55682012-01-30 18:28:39 +0000473 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000474 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000475 GetterSetterMap map;
476
477 // Build a map, pairing get/set values together.
478 for (PropertyListNode* q = p; q; q = q->m_next) {
479 PropertyNode* node = q->m_node;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000480 if (node->m_type & PropertyNode::Computed) {
481 hasComputedProperty = true;
482 break;
483 }
484 if (node->m_type & PropertyNode::Constant)
barraclough@apple.com09a55682012-01-30 18:28:39 +0000485 continue;
486
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000487 // Duplicates are possible.
488 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
oliver@apple.com72d38322013-10-21 19:23:24 +0000489 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000490 if (!result.isNewEntry) {
491 if (result.iterator->value.first->m_type == node->m_type)
492 result.iterator->value.first = node;
493 else
494 result.iterator->value.second = node;
495 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000496 }
497
498 // Iterate over the remaining properties in the list.
499 for (; p; p = p->m_next) {
500 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000501
502 // Handle regular values.
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000503 if (node->m_type & PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000504 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000505 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000506 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000507
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000508 RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000509 bool needsSuperBinding = node->needsSuperBinding();
510 if (needsSuperBinding)
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000511 emitPutHomeObject(generator, value.get(), dst);
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000512
513 unsigned attributes = node->isClassProperty() ? (Accessor | DontEnum) : Accessor;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000514
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000515 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
516
517 // This is a get/set property which may be overridden by a computed property later.
518 if (hasComputedProperty) {
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000519 // Computed accessors.
520 if (node->m_type & PropertyNode::Computed) {
521 RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000522 generator.emitSetFunctionNameIfNeeded(node->m_assign, value.get(), propertyName.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000523 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000524 generator.emitPutGetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000525 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000526 generator.emitPutSetterByVal(dst, propertyName.get(), attributes, value.get());
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000527 continue;
528 }
529
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000530 if (node->m_type & PropertyNode::Getter)
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000531 generator.emitPutGetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000532 else
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000533 generator.emitPutSetterById(dst, *node->name(), attributes, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000534 continue;
535 }
536
537 // This is a get/set property pair.
oliver@apple.com72d38322013-10-21 19:23:24 +0000538 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000539 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000540 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000541
542 // Was this already generated as a part of its partner?
543 if (pair.second == node)
544 continue;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000545
barraclough@apple.com09a55682012-01-30 18:28:39 +0000546 // Generate the paired node now.
547 RefPtr<RegisterID> getterReg;
548 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000549 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000550
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000551 if (node->m_type & PropertyNode::Getter) {
barraclough@apple.com09a55682012-01-30 18:28:39 +0000552 getterReg = value;
553 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000554 ASSERT(pair.second->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000555 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000556 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000557 } else {
558 setterReg = generator.newTemporary();
559 generator.emitLoad(setterReg.get(), jsUndefined());
560 }
561 } else {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000562 ASSERT(node->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000563 setterReg = value;
564 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000565 ASSERT(pair.second->m_type & PropertyNode::Getter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000566 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000567 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000568 } else {
569 getterReg = generator.newTemporary();
570 generator.emitLoad(getterReg.get(), jsUndefined());
571 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000572 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000573
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000574 ASSERT(!pair.second || needsSuperBinding == pair.second->needsSuperBinding());
575 if (needsSuperBinding && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000576 emitPutHomeObject(generator, secondReg, dst);
577
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000578 generator.emitPutGetterSetter(dst, *node->name(), attributes, getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000579 }
580 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000581
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000582 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000583}
584
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000585void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
586{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000587 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000588 if (node.needsSuperBinding()) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000589 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000590
591 RefPtr<RegisterID> propertyNameRegister;
592 if (node.name())
593 propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node.name());
594 else
595 propertyNameRegister = generator.emitNode(node.m_expression);
596
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000597 unsigned attributes = BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable;
598 if (!node.isClassProperty())
599 attributes |= BytecodeGenerator::PropertyEnumerable;
600 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyNameRegister.get());
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000601 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(),
ggaren@apple.comcadd8c52016-04-22 23:04:55 +0000602 value.get(), nullptr, nullptr, attributes, m_position);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000603 return;
604 }
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000605 if (const auto* identifier = node.name()) {
606 Optional<uint32_t> optionalIndex = parseIndex(*identifier);
607 if (!optionalIndex) {
608 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
609 return;
610 }
611
612 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
613 generator.emitDirectPutByVal(newObj, index.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000614 return;
615 }
616 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
mark.lam@apple.com47c2f142016-03-16 18:16:32 +0000617 generator.emitSetFunctionNameIfNeeded(node.m_assign, value.get(), propertyName.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000618 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000619}
620
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000621// ------------------------------ BracketAccessorNode --------------------------------
622
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000623static bool isNonIndexStringElement(ExpressionNode& element)
624{
625 return element.isString() && !parseIndex(static_cast<StringNode&>(element).value());
626}
627
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000628RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
629{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000630 if (m_base->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000631 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
632 RefPtr<RegisterID> thisValue = generator.ensureThis();
633 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000634 if (isNonIndexStringElement(*m_subscript)) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000635 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
sbarati@apple.com23315d62016-05-09 20:17:23 +0000636 generator.emitGetById(finalDest.get(), superBase.get(), thisValue.get(), id);
637 } else {
638 RefPtr<RegisterID> subscript = generator.emitNode(m_subscript);
639 generator.emitGetByVal(finalDest.get(), superBase.get(), thisValue.get(), subscript.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000640 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000641
642 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
643 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
644 return finalDest.get();
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000645 }
646
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000647 RegisterID* ret;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000648 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000649
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000650 if (isNonIndexStringElement(*m_subscript)) {
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000651 RefPtr<RegisterID> base = generator.emitNode(m_base);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000652 ret = generator.emitGetById(finalDest.get(), base.get(), static_cast<StringNode*>(m_subscript)->value());
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000653 } else {
654 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
655 RegisterID* property = generator.emitNode(m_subscript);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000656 ret = generator.emitGetByVal(finalDest.get(), base.get(), property);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000657 }
658
659 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
660
sbarati@apple.com23315d62016-05-09 20:17:23 +0000661 generator.emitProfileType(finalDest.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000662 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000663}
664
665// ------------------------------ DotAccessorNode --------------------------------
666
667RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
668{
sbarati@apple.com23315d62016-05-09 20:17:23 +0000669 bool baseIsSuper = m_base->isSuperNode();
670 RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000671 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000672 RegisterID* finalDest = generator.finalDestination(dst);
sbarati@apple.com23315d62016-05-09 20:17:23 +0000673 RegisterID* ret;
674 if (baseIsSuper) {
675 RefPtr<RegisterID> thisValue = generator.ensureThis();
676 ret = generator.emitGetById(finalDest, base.get(), thisValue.get(), m_ident);
677 } else
678 ret = generator.emitGetById(finalDest, base.get(), m_ident);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000679 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000680 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000681}
682
683// ------------------------------ ArgumentListNode -----------------------------
684
685RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
686{
687 ASSERT(m_expr);
688 return generator.emitNode(dst, m_expr);
689}
690
691// ------------------------------ NewExprNode ----------------------------------
692
693RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
694{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000695 ExpectedFunction expectedFunction;
696 if (m_expr->isResolveNode())
697 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
698 else
699 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000700 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000701 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000702 CallArguments callArguments(generator, m_args);
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000703 generator.emitMove(callArguments.thisRegister(), func.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000704 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000705}
706
oliver@apple.com72f8a822013-10-17 01:02:34 +0000707CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000708 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000709 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000710{
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000711 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000712 if (argumentsNode) {
713 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
714 ++argumentCountIncludingThis;
715 }
716
717 m_argv.grow(argumentCountIncludingThis);
718 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
719 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000720 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 +0000721 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000722
723 // We need to ensure that the frame size is stack-aligned
724 while ((JSStack::CallFrameHeaderSize + m_argv.size()) % stackAlignmentRegisters()) {
725 m_argv.insert(0, generator.newTemporary());
726 m_padding++;
727 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000728
729 while (stackOffset() % stackAlignmentRegisters()) {
730 m_argv.insert(0, generator.newTemporary());
731 m_padding++;
732 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000733}
734
735// ------------------------------ EvalFunctionCallNode ----------------------------------
736
737RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
738{
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000739 // We need try to load 'this' before call eval in constructor, because 'this' can created by 'super' in some of the arrow function
740 // var A = class A {
741 // constructor () { this.id = 'A'; }
742 // }
743 //
744 // var B = class B extend A {
745 // constructor () {
746 // var arrow = () => super();
747 // arrow();
748 // eval("this.id = 'B'");
749 // }
750 // }
gskachkov@gmail.coma198dd12016-02-28 19:14:26 +0000751 if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isThisUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000752 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
753
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000754 Variable var = generator.variable(generator.propertyNames().eval);
755 if (RegisterID* local = var.local()) {
756 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000757 CallArguments callArguments(generator, m_args);
758 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000759 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000760 }
761
762 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000763 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000764 JSTextPosition newDivot = divotStart() + 4;
765 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000766 generator.moveToDestinationIfNeeded(
767 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000768 generator.emitResolveScope(callArguments.thisRegister(), var));
769 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000770 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000771}
772
773// ------------------------------ FunctionCallValueNode ----------------------------------
774
775RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
776{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000777 if (m_expr->isSuperNode()) {
sbarati@apple.com23315d62016-05-09 20:17:23 +0000778 RefPtr<RegisterID> func = emitGetSuperFunctionForConstruct(generator);
779 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
780 CallArguments callArguments(generator, m_args);
781
commit-queue@webkit.orgefc86f52015-12-30 21:08:16 +0000782 ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
783 ASSERT(generator.constructorKind() == ConstructorKind::Derived || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000784 generator.emitMove(callArguments.thisRegister(), generator.newTarget());
785 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000786
787 bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Derived;
788 bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived && generator.needsToUpdateArrowFunctionContext();
789
790 if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor && generator.isSuperCallUsedInInnerArrowFunction()))
791 generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
792
793 RefPtr<Label> thisIsEmptyLabel = generator.newLabel();
794 generator.emitJumpIfTrue(generator.emitIsEmpty(generator.newTemporary(), generator.thisRegister()), thisIsEmptyLabel.get());
795 generator.emitThrowReferenceError(ASCIILiteral("'super()' can't be called more than once in a constructor."));
796 generator.emitLabel(thisIsEmptyLabel.get());
797
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000798 generator.emitMove(generator.thisRegister(), ret);
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000799
gskachkov@gmail.com086f8f62016-04-26 18:40:41 +0000800 if (generator.isDerivedConstructorContext() || doWeUseArrowFunctionInConstructor)
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +0000801 generator.emitPutThisToArrowFunctionContextScope();
commit-queue@webkit.orgabdc6172016-02-24 20:46:44 +0000802
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000803 return ret;
804 }
sbarati@apple.com23315d62016-05-09 20:17:23 +0000805 RefPtr<RegisterID> func = generator.emitNode(m_expr);
806 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
807 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000808 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000809 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000810 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000811 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000812}
813
814// ------------------------------ FunctionCallResolveNode ----------------------------------
815
816RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
817{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000818 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000819
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000820 Variable var = generator.variable(m_ident);
821 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000822 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000823 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000824 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000825 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000826 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000827 // This passes NoExpectedFunction because we expect that if the function is in a
828 // local variable, then it's not one of our built-in constructors.
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000829 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000830 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000831 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000832 }
833
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000834 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000835 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000836 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000837
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000838 JSTextPosition newDivot = divotStart() + m_ident.length();
839 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000840 generator.moveToDestinationIfNeeded(
841 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000842 generator.emitResolveScope(callArguments.thisRegister(), var));
843 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000844 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000845 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000846 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000847 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000848}
849
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000850// ------------------------------ BytecodeIntrinsicNode ----------------------------------
851
852RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
853{
854 return (this->*m_emitter)(generator, dst);
855}
856
keith_miller@apple.com85aeabb2016-06-03 23:06:39 +0000857RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argumentCount(BytecodeGenerator& generator, RegisterID* dst)
858{
859 ASSERT(!m_args->m_listNode);
860
861 return generator.emitUnaryNoDstOp(op_argument_count, generator.finalDestination(dst));
862}
863
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +0000864RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator& generator, RegisterID* dst)
865{
866#ifndef NDEBUG
867 ArgumentListNode* node = m_args->m_listNode;
868 RefPtr<RegisterID> condition = generator.emitNode(node);
869 generator.emitAssert(condition.get(), node->firstLine());
870 return dst;
871#else
872 UNUSED_PARAM(generator);
873 return dst;
874#endif
875}
876
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000877RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
878{
879 ArgumentListNode* node = m_args->m_listNode;
880 RefPtr<RegisterID> base = generator.emitNode(node);
881 node = node->m_next;
882 RefPtr<RegisterID> index = generator.emitNode(node);
883 node = node->m_next;
884 RefPtr<RegisterID> value = generator.emitNode(node);
885
886 ASSERT(!node->m_next);
887
888 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
889}
890
keith_miller@apple.come497e202016-06-13 21:05:36 +0000891RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator& generator, RegisterID* dst)
892{
893 ArgumentListNode* node = m_args->m_listNode;
894 RefPtr<RegisterID> function = generator.emitNode(node);
895 node = node->m_next;
896 RefPtr<RegisterID> thisRegister = generator.emitNode(node);
897 ASSERT(!node->m_next);
898
899 RefPtr<RegisterID> finalDst = generator.finalDestination(dst);
900 return generator.emitCallForwardArgumentsInTailPosition(finalDst.get(), function.get(), thisRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd());
901}
902
keith_miller@apple.com8844d302016-04-07 19:38:00 +0000903RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tryGetById(BytecodeGenerator& generator, RegisterID* dst)
904{
905 ArgumentListNode* node = m_args->m_listNode;
906 RefPtr<RegisterID> base = generator.emitNode(node);
907 node = node->m_next;
908
909 // Since this is a builtin we expect the creator to use a string literal as the second argument.
910 ASSERT(node->m_expr->isString());
911 const Identifier& ident = static_cast<StringNode*>(node->m_expr)->value();
912 ASSERT(!node->m_next);
913
keith_miller@apple.come497e202016-06-13 21:05:36 +0000914 RefPtr<RegisterID> finalDest = generator.finalDestination(dst);
915 return generator.emitTryGetById(finalDest.get(), base.get(), ident);
keith_miller@apple.com8844d302016-04-07 19:38:00 +0000916}
917
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +0000918RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
919{
920 ArgumentListNode* node = m_args->m_listNode;
921 RefPtr<RegisterID> src = generator.emitNode(node);
922 ASSERT(!node->m_next);
923
924 return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
925}
926
utatane.tea@gmail.com0f56f572016-02-08 23:14:47 +0000927RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
928{
929 ArgumentListNode* node = m_args->m_listNode;
930 RefPtr<RegisterID> src = generator.emitNode(node);
931 ASSERT(!node->m_next);
932
933 return generator.moveToDestinationIfNeeded(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
934}
935
utatane.tea@gmail.combf8978b2016-02-02 19:33:05 +0000936
937#define JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS(name) \
938 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_##name(BytecodeGenerator& generator, RegisterID* dst) \
939 { \
940 ASSERT(!m_args); \
941 ASSERT(type() == Type::Constant); \
942 if (dst == generator.ignoredResult()) \
943 return nullptr; \
944 return generator.emitLoad(dst, generator.vm()->bytecodeIntrinsicRegistry().name##Value(generator)); \
945 }
946 JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS)
947#undef JSC_DECLARE_BYTECODE_INTRINSIC_CONSTANT_GENERATORS
948
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000949// ------------------------------ FunctionCallBracketNode ----------------------------------
950
951RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
952{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000953 bool baseIsSuper = m_base->isSuperNode();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000954 bool subscriptIsNonIndexString = isNonIndexStringElement(*m_subscript);
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +0000955
956 RefPtr<RegisterID> base;
957 if (baseIsSuper)
958 base = emitSuperBaseForCallee(generator);
959 else {
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000960 if (subscriptIsNonIndexString)
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +0000961 base = generator.emitNode(m_base);
962 else
963 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
964 }
965
966 RefPtr<RegisterID> function;
sbarati@apple.com23315d62016-05-09 20:17:23 +0000967 RefPtr<RegisterID> thisRegister;
968 if (baseIsSuper) {
969 // 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.
970 thisRegister = generator.ensureThis();
971 }
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +0000972 if (subscriptIsNonIndexString) {
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +0000973 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000974 if (baseIsSuper)
975 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisRegister.get(), static_cast<StringNode*>(m_subscript)->value());
976 else
977 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +0000978 } else {
979 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
980 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000981 if (baseIsSuper)
982 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisRegister.get(), property.get());
983 else
984 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +0000985 }
986
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000987 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000988 CallArguments callArguments(generator, m_args);
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +0000989 if (baseIsSuper) {
990 generator.emitTDZCheck(generator.thisRegister());
sbarati@apple.com23315d62016-05-09 20:17:23 +0000991 generator.emitMove(callArguments.thisRegister(), thisRegister.get());
gskachkov@gmail.comc307ee42016-04-28 15:12:10 +0000992 } else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000993 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000994 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000995 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000996 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000997}
998
999// ------------------------------ FunctionCallDotNode ----------------------------------
1000
1001RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1002{
1003 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001004 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001005 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001006 bool baseIsSuper = m_base->isSuperNode();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001007 if (baseIsSuper)
1008 generator.emitMove(callArguments.thisRegister(), generator.ensureThis());
1009 else
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001010 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001011 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001012 if (baseIsSuper) {
1013 RefPtr<RegisterID> superBase = emitSuperBaseForCallee(generator);
1014 generator.emitGetById(function.get(), superBase.get(), callArguments.thisRegister(), m_ident);
1015 } else
1016 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001017 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001018 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001019 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001020}
1021
1022RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1023{
1024 RefPtr<Label> realCall = generator.newLabel();
1025 RefPtr<Label> end = generator.newLabel();
1026 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001027 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001028 RefPtr<RegisterID> function;
oliver@apple.comba848d12014-02-12 17:14:23 +00001029 bool emitCallCheck = !generator.isBuiltinFunction();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001030 if (emitCallCheck) {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001031 if (m_base->isSuperNode()) {
1032 RefPtr<RegisterID> thisValue = generator.ensureThis();
1033 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().callPublicName());
1034 } else
1035 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +00001036 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001037 }
1038 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001039 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001040 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 +00001041 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
1042 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001043 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001044 argumentsRegister = generator.emitNode(subject);
1045 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
1046 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
joepeck@webkit.orgc10e46b2016-05-21 05:17:24 +00001047 generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, divot(), divotStart(), divotEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001048 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001049 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001050 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +00001051
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001052 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1053 CallArguments callArguments(generator, m_args);
1054 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001055 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001056 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001057 } else {
1058 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1059 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +00001060 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001061 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001062 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001063 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001064 if (emitCallCheck) {
1065 generator.emitJump(end.get());
1066 generator.emitLabel(realCall.get());
1067 {
1068 CallArguments callArguments(generator, m_args);
1069 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001070 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001071 }
1072 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001073 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001074 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001075 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001076}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001077
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001078static bool areTrivialApplyArguments(ArgumentsNode* args)
1079{
1080 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
1081 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
1082}
1083
1084RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1085{
1086 // A few simple cases can be trivially handled as ordinary function calls.
1087 // function.apply(), function.apply(arg) -> identical to function.call
1088 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
1089 bool mayBeCall = areTrivialApplyArguments(m_args);
1090
1091 RefPtr<Label> realCall = generator.newLabel();
1092 RefPtr<Label> end = generator.newLabel();
1093 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001094 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001095 RefPtr<RegisterID> function;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001096 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001097 bool emitCallCheck = !generator.isBuiltinFunction();
1098 if (emitCallCheck) {
sbarati@apple.com23315d62016-05-09 20:17:23 +00001099 if (m_base->isSuperNode()) {
1100 RefPtr<RegisterID> thisValue = generator.ensureThis();
1101 function = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), generator.propertyNames().builtinNames().applyPublicName());
1102 } else
1103 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +00001104 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
1105 }
1106 if (mayBeCall) {
1107 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
1108 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001109 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
1110 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001111 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
1112 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
1113 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1114 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
1115
1116 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
1117 {
1118 RefPtr<Label> haveThis = generator.newLabel();
1119 RefPtr<Label> end = generator.newLabel();
1120 RefPtr<RegisterID> compareResult = generator.newTemporary();
1121 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1122 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
1123 generator.emitMove(thisRegister.get(), value);
1124 generator.emitLoad(index.get(), jsNumber(1));
1125 generator.emitJump(end.get());
1126 generator.emitLabel(haveThis.get());
1127 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
1128 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
1129 generator.emitMove(argumentsRegister.get(), value);
1130 generator.emitLoad(index.get(), jsNumber(2));
1131 generator.emitLabel(end.get());
1132 };
1133 generator.emitEnumeration(this, spread->expression(), extractor);
joepeck@webkit.orgc10e46b2016-05-21 05:17:24 +00001134 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd());
oliver@apple.com0989d9b2014-02-26 20:40:46 +00001135 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +00001136 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
1137 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +00001138 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 +00001139 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1140 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +00001141 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001142 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001143 } else {
1144 m_args->m_listNode = m_args->m_listNode->m_next;
1145 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1146 CallArguments callArguments(generator, m_args);
1147 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001148 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001149 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001150 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001151 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +00001152 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +00001153 CallArguments callArguments(generator, m_args);
1154 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001155 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001156 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001157 } else {
1158 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
oliver@apple.comba848d12014-02-12 17:14:23 +00001159 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1160 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
1161 RefPtr<RegisterID> argsRegister;
1162 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001163 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +00001164
1165 // Function.prototype.apply ignores extra arguments, but we still
1166 // need to evaluate them for side effects.
1167 while ((args = args->m_next))
1168 generator.emitNode(args->m_expr);
1169
joepeck@webkit.orgc10e46b2016-05-21 05:17:24 +00001170 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, divot(), divotStart(), divotEnd());
oliver@apple.comd04e0a02014-02-01 01:37:59 +00001171 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001172 if (emitCallCheck) {
1173 generator.emitJump(end.get());
1174 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001175 CallArguments callArguments(generator, m_args);
1176 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001177 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001178 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001179 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001180 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001181 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001182}
1183
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001184// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001185
ggaren@apple.comf3036112013-04-27 23:14:04 +00001186static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001187{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001188 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001189}
1190
1191static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1192{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001193 if (dst == srcDst)
1194 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1195 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1196 emitIncOrDec(generator, srcDst, oper);
1197 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001198}
1199
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001200RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001201{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001202 if (dst == generator.ignoredResult())
1203 return PrefixNode::emitResolve(generator, dst);
1204
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001205 ASSERT(m_expr->isResolveNode());
1206 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1207 const Identifier& ident = resolve->identifier();
1208
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001209 Variable var = generator.variable(ident);
1210 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001211 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001212 RefPtr<RegisterID> localReg = local;
1213 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001214 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001215 localReg = generator.emitMove(generator.tempDestination(dst), local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001216 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001217 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1218 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1219 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001220 }
oliver@apple.com75f804e2013-03-07 00:25:20 +00001221
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001222 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001223 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1224 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001225 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001226 if (var.isReadOnly()) {
1227 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1228 if (threwException)
1229 return value.get();
1230 }
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001231 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001232 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001233 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001234 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1235 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001236
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001237 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001238}
1239
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001240RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001241{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001242 if (dst == generator.ignoredResult())
1243 return PrefixNode::emitBracket(generator, dst);
1244
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001245 ASSERT(m_expr->isBracketAccessorNode());
1246 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1247 ExpressionNode* baseNode = bracketAccessor->base();
1248 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001249
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001250 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001251 RefPtr<RegisterID> property = generator.emitNode(subscript);
1252
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001253 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001254 RefPtr<RegisterID> value;
1255 RefPtr<RegisterID> thisValue;
1256 if (baseNode->isSuperNode()) {
1257 thisValue = generator.ensureThis();
1258 value = generator.emitGetByVal(generator.newTemporary(), base.get(), thisValue.get(), property.get());
1259 } else
1260 value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001261 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001262 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001263 if (baseNode->isSuperNode())
1264 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value.get());
1265 else
1266 generator.emitPutByVal(base.get(), property.get(), value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001267 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001268 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001269}
1270
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001271RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001272{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001273 if (dst == generator.ignoredResult())
1274 return PrefixNode::emitDot(generator, dst);
1275
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001276 ASSERT(m_expr->isDotAccessorNode());
1277 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1278 ExpressionNode* baseNode = dotAccessor->base();
sbarati@apple.com23315d62016-05-09 20:17:23 +00001279 bool baseIsSuper = baseNode->isSuperNode();
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001280 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001281
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001282 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1283
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001284 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001285 RefPtr<RegisterID> value;
1286 RefPtr<RegisterID> thisValue;
1287 if (baseIsSuper) {
1288 thisValue = generator.ensureThis();
1289 value = generator.emitGetById(generator.newTemporary(), base.get(), thisValue.get(), ident);
1290 } else
1291 value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001292 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001293 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001294 if (baseIsSuper)
1295 generator.emitPutById(base.get(), thisValue.get(), ident, value.get());
1296 else
1297 generator.emitPutById(base.get(), ident, value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001298 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001299 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001300}
1301
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001302RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001303{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001304 if (m_expr->isResolveNode())
1305 return emitResolve(generator, dst);
1306
1307 if (m_expr->isBracketAccessorNode())
1308 return emitBracket(generator, dst);
1309
1310 if (m_expr->isDotAccessorNode())
1311 return emitDot(generator, dst);
1312
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001313 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001314 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1315 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001316}
1317
1318// ------------------------------ DeleteResolveNode -----------------------------------
1319
1320RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1321{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001322 Variable var = generator.variable(m_ident);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001323 if (var.local()) {
1324 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001325 return generator.emitLoad(generator.finalDestination(dst), false);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001326 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001327
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001328 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001329 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001330 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
oliver@apple.com58c86752013-07-25 04:02:40 +00001331 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001332}
1333
1334// ------------------------------ DeleteBracketNode -----------------------------------
1335
1336RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1337{
1338 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001339 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001340
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001341 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001342 if (m_base->isSuperNode())
1343 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001344 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001345}
1346
1347// ------------------------------ DeleteDotNode -----------------------------------
1348
1349RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1350{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001351 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001352
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001353 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001354 if (m_base->isSuperNode())
1355 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001356 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001357}
1358
1359// ------------------------------ DeleteValueNode -----------------------------------
1360
1361RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1362{
1363 generator.emitNode(generator.ignoredResult(), m_expr);
1364
1365 // delete on a non-location expression ignores the value and returns true
1366 return generator.emitLoad(generator.finalDestination(dst), true);
1367}
1368
1369// ------------------------------ VoidNode -------------------------------------
1370
1371RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1372{
1373 if (dst == generator.ignoredResult()) {
1374 generator.emitNode(generator.ignoredResult(), m_expr);
1375 return 0;
1376 }
1377 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1378 return generator.emitLoad(dst, jsUndefined());
1379}
1380
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001381// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001382
1383RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1384{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001385 Variable var = generator.variable(m_ident);
1386 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001387 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001388 if (dst == generator.ignoredResult())
1389 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001390 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001391 }
1392
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001393 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1394 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001395 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001396 if (dst == generator.ignoredResult())
1397 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001398 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001399}
1400
1401// ------------------------------ TypeOfValueNode -----------------------------------
1402
1403RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1404{
1405 if (dst == generator.ignoredResult()) {
1406 generator.emitNode(generator.ignoredResult(), m_expr);
1407 return 0;
1408 }
1409 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1410 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1411}
1412
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001413// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001414
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001415RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001416{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001417 ASSERT(m_expr->isResolveNode());
1418 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1419 const Identifier& ident = resolve->identifier();
1420
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001421 Variable var = generator.variable(ident);
1422 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001423 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001424 RefPtr<RegisterID> localReg = local;
1425 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001426 generator.emitReadOnlyExceptionIfNeeded(var);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001427 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001428 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001429 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001430 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001431 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001432 generator.emitMove(localReg.get(), tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001433 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001434 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1435 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001436 emitIncOrDec(generator, localReg.get(), m_operator);
1437 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001438 }
1439
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001440 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001441 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1442 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001443 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001444 if (var.isReadOnly()) {
1445 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1446 if (threwException)
1447 return value.get();
1448 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001449
oliver@apple.com58c86752013-07-25 04:02:40 +00001450 emitIncOrDec(generator, value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001451 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00001452 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001453 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1454 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001455 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001456}
1457
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001458RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001459{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001460 ASSERT(m_expr->isBracketAccessorNode());
1461 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1462 ExpressionNode* baseNode = bracketAccessor->base();
1463 ExpressionNode* subscript = bracketAccessor->subscript();
1464
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001465 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001466 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001467 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1468
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001469 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001470 RegisterID* value;
1471 RefPtr<RegisterID> thisValue;
1472 if (baseNode->isSuperNode()) {
1473 thisValue = generator.ensureThis();
1474 value = generator.emitGetByVal(propDst.get(), base.get(), thisValue.get(), property.get());
1475 } else
1476 value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001477 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001478 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001479 if (baseNode->isSuperNode())
1480 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
1481 else
1482 generator.emitPutByVal(base.get(), property.get(), value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001483 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001484 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1485}
1486
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001487RegisterID* PrefixNode::emitDot(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->isDotAccessorNode());
1490 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1491 ExpressionNode* baseNode = dotAccessor->base();
1492 const Identifier& ident = dotAccessor->identifier();
1493
1494 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001495 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1496
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001497 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001498 RegisterID* value;
1499 RefPtr<RegisterID> thisValue;
1500 if (baseNode->isSuperNode()) {
1501 thisValue = generator.ensureThis();
1502 value = generator.emitGetById(propDst.get(), base.get(), thisValue.get(), ident);
1503 } else
1504 value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001505 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001506 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00001507 if (baseNode->isSuperNode())
1508 generator.emitPutById(base.get(), thisValue.get(), ident, value);
1509 else
1510 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001511 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001512 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1513}
1514
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001515RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001516{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001517 if (m_expr->isResolveNode())
1518 return emitResolve(generator, dst);
1519
1520 if (m_expr->isBracketAccessorNode())
1521 return emitBracket(generator, dst);
1522
1523 if (m_expr->isDotAccessorNode())
1524 return emitDot(generator, dst);
1525
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001526 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001527 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1528 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001529}
1530
1531// ------------------------------ Unary Operation Nodes -----------------------------------
1532
1533RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1534{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001535 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001536 generator.emitExpressionInfo(position(), position(), position());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001537 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001538}
1539
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001540// ------------------------------ BitwiseNotNode -----------------------------------
1541
1542RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1543{
1544 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001545 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1546 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 +00001547}
1548
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001549// ------------------------------ LogicalNotNode -----------------------------------
1550
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001551void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001552{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001553 // reverse the true and false targets
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001554 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001555}
1556
1557
1558// ------------------------------ Binary Operation Nodes -----------------------------------
1559
1560// BinaryOpNode::emitStrcat:
1561//
1562// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1563// more values, where we can determine a set of separate op_add operations would be operating on
1564// string values.
1565//
1566// This function expects to be operating on a graph of AST nodes looking something like this:
1567//
1568// (a)... (b)
1569// \ /
1570// (+) (c)
1571// \ /
1572// [d] ((+))
1573// \ /
1574// [+=]
1575//
1576// The assignment operation is optional, if it exists the register holding the value on the
1577// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1578//
1579// The method should be called on the node at the root of the tree of regular binary add
1580// operations (marked in the diagram with a double set of parentheses). This node must
1581// be performing a string concatenation (determined by statically detecting that at least
1582// one child must be a string).
1583//
1584// Since the minimum number of values being concatenated together is expected to be 3, if
1585// a lhs to a concatenating assignment is not provided then the root add should have at
1586// least one left child that is also an add that can be determined to be operating on strings.
1587//
1588RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1589{
1590 ASSERT(isAdd());
1591 ASSERT(resultDescriptor().definitelyIsString());
1592
1593 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1594 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1595 // added first, and the leftmost child is never added, so the vector produced for the
1596 // example above will be [ c, b ].
1597 Vector<ExpressionNode*, 16> reverseExpressionList;
1598 reverseExpressionList.append(m_expr2);
1599
1600 // Examine the left child of the add. So long as this is a string add, add its right-child
1601 // to the list, and keep processing along the left fork.
1602 ExpressionNode* leftMostAddChild = m_expr1;
1603 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1604 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1605 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1606 }
1607
1608 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1609
1610 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1611 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1612 // op_strcat node handle its conversion if required).
1613 if (lhs)
1614 temporaryRegisters.append(generator.newTemporary());
1615
1616 // Emit code for the leftmost node ((a) in the example).
1617 temporaryRegisters.append(generator.newTemporary());
1618 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1619 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1620
1621 // Note on ordering of conversions:
1622 //
1623 // We maintain the same ordering of conversions as we would see if the concatenations
1624 // was performed as a sequence of adds (otherwise this optimization could change
1625 // behaviour should an object have been provided a valueOf or toString method).
1626 //
1627 // Considering the above example, the sequnce of execution is:
1628 // * evaluate operand (a)
1629 // * evaluate operand (b)
1630 // * convert (a) to primitive <- (this would be triggered by the first add)
1631 // * convert (b) to primitive <- (ditto)
1632 // * evaluate operand (c)
1633 // * convert (c) to primitive <- (this would be triggered by the second add)
1634 // And optionally, if there is an assignment:
1635 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1636 //
1637 // As such we do not plant an op to convert the leftmost child now. Instead, use
1638 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1639 // once the second node has been generated. However, if the leftmost child is an
1640 // immediate we can trivially determine that no conversion will be required.
1641 // If this is the case
1642 if (leftMostAddChild->isString())
1643 leftMostAddChildTempRegister = 0;
1644
1645 while (reverseExpressionList.size()) {
1646 ExpressionNode* node = reverseExpressionList.last();
1647 reverseExpressionList.removeLast();
1648
1649 // Emit the code for the current node.
1650 temporaryRegisters.append(generator.newTemporary());
1651 generator.emitNode(temporaryRegisters.last().get(), node);
1652
1653 // On the first iteration of this loop, when we first reach this point we have just
1654 // generated the second node, which means it is time to convert the leftmost operand.
1655 if (leftMostAddChildTempRegister) {
1656 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1657 leftMostAddChildTempRegister = 0; // Only do this once.
1658 }
1659 // Plant a conversion for this node, if necessary.
1660 if (!node->isString())
1661 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1662 }
1663 ASSERT(temporaryRegisters.size() >= 3);
1664
1665 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1666 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1667 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001668 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001669 // If there is an assignment convert the lhs now. This will also copy lhs to
1670 // the temporary register we allocated for it.
1671 if (lhs)
1672 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1673
1674 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1675}
1676
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001677void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1678{
1679 TriState branchCondition;
1680 ExpressionNode* branchExpression;
1681 tryFoldToBranch(generator, branchCondition, branchExpression);
1682
1683 if (branchCondition == MixedTriState)
1684 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1685 else if (branchCondition == TrueTriState)
1686 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1687 else
1688 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1689}
1690
1691static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1692{
1693 ResultType expressionType = branchExpression->resultDescriptor();
1694
1695 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1696 return true;
1697 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1698 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1699 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1700 return true;
1701
1702 return false;
1703}
1704
1705void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1706{
1707 branchCondition = MixedTriState;
1708 branchExpression = 0;
1709
1710 ConstantNode* constant = 0;
1711 if (m_expr1->isConstant()) {
1712 constant = static_cast<ConstantNode*>(m_expr1);
1713 branchExpression = m_expr2;
1714 } else if (m_expr2->isConstant()) {
1715 constant = static_cast<ConstantNode*>(m_expr2);
1716 branchExpression = m_expr1;
1717 }
1718
1719 if (!constant)
1720 return;
1721 ASSERT(branchExpression);
1722
1723 OpcodeID opcodeID = this->opcodeID();
1724 JSValue value = constant->jsValue(generator);
1725 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1726 if (!canFoldToBranch)
1727 return;
1728
1729 if (opcodeID == op_eq || opcodeID == op_stricteq)
1730 branchCondition = triState(value.pureToBoolean());
1731 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1732 branchCondition = triState(!value.pureToBoolean());
1733}
1734
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001735RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1736{
1737 OpcodeID opcodeID = this->opcodeID();
1738
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001739 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001740 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001741 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001742 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001743
1744 if (opcodeID == op_neq) {
1745 if (m_expr1->isNull() || m_expr2->isNull()) {
1746 RefPtr<RegisterID> src = generator.tempDestination(dst);
1747 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1748 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1749 }
1750 }
1751
oliver@apple.comece74042012-12-01 00:50:39 +00001752 ExpressionNode* left = m_expr1;
1753 ExpressionNode* right = m_expr2;
1754 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1755 if (left->isString())
1756 std::swap(left, right);
1757 }
1758
1759 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001760 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001761 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001762 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001763 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001764 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1765 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001766 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001767 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001768 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001769 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001770 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001771 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1772 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001773 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 +00001774 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1775 return generator.emitUnaryOp(op_unsigned, result, result);
1776 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001777}
1778
1779RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1780{
1781 if (m_expr1->isNull() || m_expr2->isNull()) {
1782 RefPtr<RegisterID> src = generator.tempDestination(dst);
1783 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1784 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1785 }
1786
oliver@apple.comece74042012-12-01 00:50:39 +00001787 ExpressionNode* left = m_expr1;
1788 ExpressionNode* right = m_expr2;
1789 if (left->isString())
1790 std::swap(left, right);
1791
1792 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001793 RefPtr<RegisterID> src2 = generator.emitNode(right);
1794 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001795}
1796
1797RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1798{
oliver@apple.comece74042012-12-01 00:50:39 +00001799 ExpressionNode* left = m_expr1;
1800 ExpressionNode* right = m_expr2;
1801 if (left->isString())
1802 std::swap(left, right);
1803
1804 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001805 RefPtr<RegisterID> src2 = generator.emitNode(right);
1806 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001807}
1808
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001809RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1810{
1811 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001812 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001813 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001814 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 +00001815}
1816
1817RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1818{
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001819 RefPtr<RegisterID> hasInstanceValue = generator.newTemporary();
1820 RefPtr<RegisterID> isObject = generator.newTemporary();
1821 RefPtr<RegisterID> isCustom = generator.newTemporary();
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001822 RefPtr<RegisterID> prototype = generator.newTemporary();
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001823 RefPtr<RegisterID> value = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1824 RefPtr<RegisterID> constructor = generator.emitNode(m_expr2);
1825 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, value.get());
1826 RefPtr<Label> custom = generator.newLabel();
1827 RefPtr<Label> done = generator.newLabel();
1828 RefPtr<Label> typeError = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001829
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001830 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001831 generator.emitIsObject(isObject.get(), constructor.get());
1832 generator.emitJumpIfFalse(isObject.get(), typeError.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001833
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001834 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001835 generator.emitGetById(hasInstanceValue.get(), constructor.get(), generator.vm()->propertyNames->hasInstanceSymbol);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001836
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001837 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
keith_miller@apple.comcb11fe42015-12-18 00:37:35 +00001838 generator.emitOverridesHasInstance(isCustom.get(), constructor.get(), hasInstanceValue.get());
1839
1840 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1841 generator.emitJumpIfTrue(isCustom.get(), custom.get());
1842
1843 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1844 generator.emitGetById(prototype.get(), constructor.get(), generator.vm()->propertyNames->prototype);
1845
1846 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1847 generator.emitInstanceOf(dstReg.get(), value.get(), prototype.get());
1848
1849 generator.emitJump(done.get());
1850
1851 generator.emitLabel(typeError.get());
1852 generator.emitThrowTypeError("Right hand side of instanceof is not an object");
1853
1854 generator.emitLabel(custom.get());
1855
1856 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1857 generator.emitInstanceOfCustom(dstReg.get(), value.get(), constructor.get(), hasInstanceValue.get());
1858
1859 generator.emitLabel(done.get());
1860
1861 return dstReg.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001862}
1863
1864// ------------------------------ LogicalOpNode ----------------------------
1865
1866RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1867{
1868 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1869 RefPtr<Label> target = generator.newLabel();
1870
1871 generator.emitNode(temp.get(), m_expr1);
1872 if (m_operator == OpLogicalAnd)
1873 generator.emitJumpIfFalse(temp.get(), target.get());
1874 else
1875 generator.emitJumpIfTrue(temp.get(), target.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001876 generator.emitNodeInTailPosition(temp.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001877 generator.emitLabel(target.get());
1878
1879 return generator.moveToDestinationIfNeeded(dst, temp.get());
1880}
1881
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001882void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001883{
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001884 RefPtr<Label> afterExpr1 = generator.newLabel();
1885 if (m_operator == OpLogicalAnd)
1886 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1887 else
1888 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1889 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001890
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001891 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001892}
1893
1894// ------------------------------ ConditionalNode ------------------------------
1895
1896RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1897{
1898 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1899 RefPtr<Label> beforeElse = generator.newLabel();
1900 RefPtr<Label> afterElse = generator.newLabel();
1901
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001902 RefPtr<Label> beforeThen = generator.newLabel();
1903 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1904 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001905
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001906 generator.emitProfileControlFlow(m_expr1->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001907 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001908 generator.emitJump(afterElse.get());
1909
1910 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001911 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001912 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001913
1914 generator.emitLabel(afterElse.get());
1915
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001916 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001917
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001918 return newDst.get();
1919}
1920
1921// ------------------------------ ReadModifyResolveNode -----------------------------------
1922
1923// FIXME: should this be moved to be a method on BytecodeGenerator?
1924static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1925{
1926 OpcodeID opcodeID;
1927 switch (oper) {
1928 case OpMultEq:
1929 opcodeID = op_mul;
1930 break;
1931 case OpDivEq:
1932 opcodeID = op_div;
1933 break;
1934 case OpPlusEq:
1935 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1936 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1937 opcodeID = op_add;
1938 break;
1939 case OpMinusEq:
1940 opcodeID = op_sub;
1941 break;
1942 case OpLShift:
1943 opcodeID = op_lshift;
1944 break;
1945 case OpRShift:
1946 opcodeID = op_rshift;
1947 break;
1948 case OpURShift:
1949 opcodeID = op_urshift;
1950 break;
1951 case OpAndEq:
1952 opcodeID = op_bitand;
1953 break;
1954 case OpXOrEq:
1955 opcodeID = op_bitxor;
1956 break;
1957 case OpOrEq:
1958 opcodeID = op_bitor;
1959 break;
1960 case OpModEq:
1961 opcodeID = op_mod;
1962 break;
1963 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001964 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001965 return dst;
1966 }
1967
1968 RegisterID* src2 = generator.emitNode(m_right);
1969
1970 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1971 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1972 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001973 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001974 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1975 if (oper == OpURShift)
1976 return generator.emitUnaryOp(op_unsigned, result, result);
1977 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001978}
1979
1980RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1981{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00001982 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001983 Variable var = generator.variable(m_ident);
1984 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001985 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001986 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001987 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001988 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1989 generator.emitProfileType(result, divotStart(), divotEnd());
1990 return result;
ggaren@apple.com6e309822012-09-05 21:44:43 +00001991 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001992
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001993 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001994 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001995 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001996 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001997 generator.emitMove(local, result.get());
1998 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001999 generator.emitProfileType(local, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002000 return generator.moveToDestinationIfNeeded(dst, result.get());
2001 }
2002
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002003 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
2004 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002005 generator.emitProfileType(result, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002006 return generator.moveToDestinationIfNeeded(dst, result);
2007 }
2008
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002009 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002010 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2011 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002012 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002013 if (var.isReadOnly()) {
2014 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2015 if (threwException)
2016 return value.get();
2017 }
oliver@apple.com58c86752013-07-25 04:02:40 +00002018 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 +00002019 RegisterID* returnResult = result.get();
2020 if (!var.isReadOnly()) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002021 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, InitializationMode::NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002022 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2023 }
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002024 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002025}
2026
sbarati@apple.come67fd782016-04-19 01:38:30 +00002027static InitializationMode initializationModeForAssignmentContext(AssignmentContext assignmentContext)
2028{
2029 switch (assignmentContext) {
2030 case AssignmentContext::DeclarationStatement:
2031 return InitializationMode::Initialization;
2032 case AssignmentContext::ConstDeclarationStatement:
2033 return InitializationMode::ConstInitialization;
2034 case AssignmentContext::AssignmentExpression:
2035 return InitializationMode::NotInitialization;
2036 }
2037
2038 ASSERT_NOT_REACHED();
2039 return InitializationMode::NotInitialization;
2040}
2041
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002042// ------------------------------ AssignResolveNode -----------------------------------
2043
2044RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2045{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002046 Variable var = generator.variable(m_ident);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002047 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002048 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002049 RegisterID* result = nullptr;
2050 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2051 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002052
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002053 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002054 result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002055 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002056 generator.emitProfileType(result, var, divotStart(), divotEnd());
2057 } else if (var.isSpecial()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002058 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
2059 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002060 generator.emitMove(local, tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002061 generator.emitProfileType(local, var, divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002062 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002063 result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
2064 } else {
2065 RegisterID* right = generator.emitNode(local, m_right);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002066 generator.emitProfileType(right, var, divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002067 generator.invalidateForInContextForLocal(local);
2068 result = generator.moveToDestinationIfNeeded(dst, right);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00002069 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002070
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002071 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002072 generator.liftTDZCheckIfPossible(var);
2073 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002074 }
2075
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002076 if (generator.isStrictMode())
2077 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002078 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002079 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
2080 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002081 if (dst == generator.ignoredResult())
2082 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00002083 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002084 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002085 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002086 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
2087 if (threwException)
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002088 return result;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002089 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002090 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002091 RegisterID* returnResult = result.get();
2092 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00002093 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_assignmentContext));
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00002094 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
2095 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002096
saambarati1@gmail.come4556722015-07-19 16:57:44 +00002097 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002098 generator.liftTDZCheckIfPossible(var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00002099 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002100}
2101
2102// ------------------------------ AssignDotNode -----------------------------------
2103
2104RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2105{
2106 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2107 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002108 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002109 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002110 RefPtr<RegisterID> forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
2111 if (m_base->isSuperNode()) {
2112 RefPtr<RegisterID> thisValue = generator.ensureThis();
2113 generator.emitPutById(base.get(), thisValue.get(), m_ident, forwardResult.get());
2114 } else
2115 generator.emitPutById(base.get(), m_ident, forwardResult.get());
2116 generator.emitProfileType(forwardResult.get(), divotStart(), divotEnd());
2117 return generator.moveToDestinationIfNeeded(dst, forwardResult.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002118}
2119
2120// ------------------------------ ReadModifyDotNode -----------------------------------
2121
2122RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2123{
2124 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
2125
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002126 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002127 RefPtr<RegisterID> value;
2128 RefPtr<RegisterID> thisValue;
2129 if (m_base->isSuperNode()) {
2130 thisValue = generator.ensureThis();
2131 value = generator.emitGetById(generator.tempDestination(dst), base.get(), thisValue.get(), m_ident);
2132 } else
2133 value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002134 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 +00002135
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002136 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002137 RegisterID* ret;
2138 if (m_base->isSuperNode())
2139 ret = generator.emitPutById(base.get(), thisValue.get(), m_ident, updatedValue);
2140 else
2141 ret = generator.emitPutById(base.get(), m_ident, updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002142 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002143 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002144}
2145
2146// ------------------------------ AssignErrorNode -----------------------------------
2147
2148RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2149{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002150 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002151}
2152
2153// ------------------------------ AssignBracketNode -----------------------------------
2154
2155RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2156{
2157 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2158 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2159 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002160 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002161
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002162 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00002163 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00002164
sbarati@apple.com23315d62016-05-09 20:17:23 +00002165 if (isNonIndexStringElement(*m_subscript)) {
2166 if (m_base->isSuperNode()) {
2167 RefPtr<RegisterID> thisValue = generator.ensureThis();
2168 generator.emitPutById(base.get(), thisValue.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2169 } else
2170 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
2171 } else {
2172 if (m_base->isSuperNode()) {
2173 RefPtr<RegisterID> thisValue = generator.ensureThis();
2174 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), forwardResult);
2175 } else
2176 generator.emitPutByVal(base.get(), property.get(), forwardResult);
2177 }
akling@apple.come09d0422014-11-13 19:18:43 +00002178
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002179 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00002180 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002181}
2182
2183// ------------------------------ ReadModifyBracketNode -----------------------------------
2184
2185RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2186{
2187 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
2188 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
2189
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002190 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002191 RefPtr<RegisterID> value;
2192 RefPtr<RegisterID> thisValue;
2193 if (m_base->isSuperNode()) {
2194 thisValue = generator.ensureThis();
2195 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), thisValue.get(), property.get());
2196 } else
2197 value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00002198 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 +00002199
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002200 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002201 if (m_base->isSuperNode())
2202 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), updatedValue);
2203 else
2204 generator.emitPutByVal(base.get(), property.get(), updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002205 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002206
2207 return updatedValue;
2208}
2209
2210// ------------------------------ CommaNode ------------------------------------
2211
2212RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2213{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002214 CommaNode* node = this;
2215 for (; node && node->next(); node = node->next())
2216 generator.emitNode(generator.ignoredResult(), node->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002217 return generator.emitNodeInTailPosition(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002218}
2219
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002220// ------------------------------ SourceElements -------------------------------
2221
2222
2223inline StatementNode* SourceElements::lastStatement() const
2224{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002225 return m_tail;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002226}
2227
2228inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2229{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00002230 for (StatementNode* statement = m_head; statement; statement = statement->next())
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002231 generator.emitNodeInTailPosition(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002232}
2233
2234// ------------------------------ BlockNode ------------------------------------
2235
2236inline StatementNode* BlockNode::lastStatement() const
2237{
2238 return m_statements ? m_statements->lastStatement() : 0;
2239}
2240
ggaren@apple.comddc6f102015-03-20 20:12:10 +00002241StatementNode* BlockNode::singleStatement() const
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002242{
2243 return m_statements ? m_statements->singleStatement() : 0;
2244}
2245
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002246void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002247{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002248 if (!m_statements)
2249 return;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002250 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002251 m_statements->emitBytecode(generator, dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002252 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002253}
2254
2255// ------------------------------ EmptyStatementNode ---------------------------
2256
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002257void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002258{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002259 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002260}
2261
2262// ------------------------------ DebuggerStatementNode ---------------------------
2263
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002264void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002265{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002266 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002267}
2268
2269// ------------------------------ ExprStatementNode ----------------------------
2270
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002271void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002272{
2273 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002274 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002275 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002276}
2277
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002278// ------------------------------ DeclarationStatement ----------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002279
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002280void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002281{
2282 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002283 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002284 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002285}
2286
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002287// ------------------------------ EmptyVarExpression ----------------------------
2288
2289RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2290{
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002291 // 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 +00002292 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002293 return nullptr;
2294
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002295 Variable var = generator.variable(m_ident);
2296 if (RegisterID* local = var.local())
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002297 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002298 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002299 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2300 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002301 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002302 }
2303
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002304 return nullptr;
2305}
2306
2307// ------------------------------ EmptyLetExpression ----------------------------
2308
2309RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2310{
2311 // Lexical declarations like 'let' must move undefined into their variables so we don't
2312 // get TDZ errors for situations like this: `let x; x;`
2313 Variable var = generator.variable(m_ident);
2314 if (RegisterID* local = var.local()) {
2315 generator.emitLoad(local, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002316 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002317 } else {
2318 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2319 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002320 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002321 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002322 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002323
sbarati@apple.coma5cf2f12016-03-29 22:11:24 +00002324 generator.liftTDZCheckIfPossible(var);
2325
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002326 // 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 +00002327 return nullptr;
2328}
2329
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002330// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002331
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002332static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002333{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002334 if (statementNode->isBlock())
2335 return static_cast<BlockNode*>(statementNode)->singleStatement();
2336 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002337}
2338
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002339bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2340 Label*& trueTarget, FallThroughMode& fallThroughMode)
2341{
2342 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2343 if (!singleStatement)
2344 return false;
2345
2346 if (singleStatement->isBreak()) {
2347 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2348 Label* target = breakNode->trivialTarget(generator);
2349 if (!target)
2350 return false;
2351 trueTarget = target;
2352 fallThroughMode = FallThroughMeansFalse;
2353 return true;
2354 }
2355
2356 if (singleStatement->isContinue()) {
2357 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2358 Label* target = continueNode->trivialTarget(generator);
2359 if (!target)
2360 return false;
2361 trueTarget = target;
2362 fallThroughMode = FallThroughMeansFalse;
2363 return true;
2364 }
2365
2366 return false;
2367}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002368
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002369void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002370{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002371 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00002372
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002373 RefPtr<Label> beforeThen = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002374 RefPtr<Label> beforeElse = generator.newLabel();
2375 RefPtr<Label> afterElse = generator.newLabel();
2376
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002377 Label* trueTarget = beforeThen.get();
2378 Label* falseTarget = beforeElse.get();
2379 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2380 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2381
2382 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002383 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002384 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002385
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002386 if (!didFoldIfBlock) {
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002387 generator.emitNodeInTailPosition(dst, m_ifBlock);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002388 if (m_elseBlock)
2389 generator.emitJump(afterElse.get());
2390 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002391
2392 generator.emitLabel(beforeElse.get());
2393
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002394 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002395 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002396 generator.emitNodeInTailPosition(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002397 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002398
2399 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002400 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2401 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002402}
2403
2404// ------------------------------ DoWhileNode ----------------------------------
2405
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002406void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002407{
oliver@apple.com6a976452013-03-11 21:02:39 +00002408 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002409
2410 RefPtr<Label> topOfLoop = generator.newLabel();
2411 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002412 generator.emitLoopHint();
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002413 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002414
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002415 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002416
2417 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002418 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002419 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002420
2421 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002422}
2423
2424// ------------------------------ WhileNode ------------------------------------
2425
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002426void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002427{
oliver@apple.com6a976452013-03-11 21:02:39 +00002428 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002429 RefPtr<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002430
ggaren@apple.com8e8bac42015-03-26 23:35:47 +00002431 generator.emitDebugHook(WillExecuteStatement, m_expr->firstLine(), m_expr->startOffset(), m_expr->lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002432 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002433
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002434 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002435 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002436
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002437 generator.emitProfileControlFlow(m_statement->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002438 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002439
2440 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002441 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002442
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002443 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002444
2445 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002446
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002447 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002448}
2449
2450// ------------------------------ ForNode --------------------------------------
2451
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002452void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002453{
oliver@apple.com6a976452013-03-11 21:02:39 +00002454 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002455
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002456 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002457 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002458
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002459 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002460
2461 if (m_expr1)
2462 generator.emitNode(generator.ignoredResult(), m_expr1);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002463
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002464 RefPtr<Label> topOfLoop = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002465 if (m_expr2)
2466 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002467
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002468 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002469 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002470 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002471
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002472 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002473
2474 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002475 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002476 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002477 if (m_expr3)
2478 generator.emitNode(generator.ignoredResult(), m_expr3);
2479
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002480 if (m_expr2)
2481 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2482 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002483 generator.emitJump(topOfLoop.get());
2484
2485 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002486 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002487 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002488}
2489
2490// ------------------------------ ForInNode ------------------------------------
2491
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002492RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002493{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002494 if (m_lexpr->isResolveNode()) {
2495 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002496 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002497 }
2498
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002499 if (m_lexpr->isDestructuringNode()) {
2500 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002501 auto binding = assignNode->bindings();
2502 if (!binding->isBindingNode())
2503 return nullptr;
2504
2505 auto simpleBinding = static_cast<BindingNode*>(binding);
2506 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002507 Variable var = generator.variable(ident);
2508 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002509 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002510 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002511 }
2512
2513 return nullptr;
2514}
2515
2516void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2517{
2518 if (m_lexpr->isResolveNode()) {
2519 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002520 Variable var = generator.variable(ident);
2521 if (RegisterID* local = var.local())
2522 generator.emitMove(local, propertyName);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002523 else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002524 if (generator.isStrictMode())
2525 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002526 RegisterID* scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002527 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002528 generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002529 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002530 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002531 return;
2532 }
2533 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002534 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2535 const Identifier& ident = assignNode->identifier();
sbarati@apple.com23315d62016-05-09 20:17:23 +00002536 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002537 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002538 if (assignNode->base()->isSuperNode()) {
2539 RefPtr<RegisterID> thisValue = generator.ensureThis();
2540 generator.emitPutById(base.get(), thisValue.get(), ident, propertyName);
2541 } else
2542 generator.emitPutById(base.get(), ident, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002543 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002544 return;
2545 }
2546 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002547 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002548 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002549 RefPtr<RegisterID> subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002550 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002551 if (assignNode->base()->isSuperNode()) {
2552 RefPtr<RegisterID> thisValue = generator.ensureThis();
2553 generator.emitPutByVal(base.get(), thisValue.get(), subscript.get(), propertyName);
2554 } else
2555 generator.emitPutByVal(base.get(), subscript.get(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002556 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002557 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002558 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002559
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002560 if (m_lexpr->isDestructuringNode()) {
2561 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002562 auto binding = assignNode->bindings();
2563 if (!binding->isBindingNode()) {
2564 assignNode->bindings()->bindValue(generator, propertyName);
2565 return;
2566 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002567
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002568 auto simpleBinding = static_cast<BindingNode*>(binding);
2569 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002570 Variable var = generator.variable(ident);
2571 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002572 assignNode->bindings()->bindValue(generator, propertyName);
2573 return;
2574 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002575 generator.emitMove(var.local(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002576 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002577 return;
2578 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002579
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002580 RELEASE_ASSERT_NOT_REACHED();
2581}
2582
2583void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
2584{
2585 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002586 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002587 return;
2588 }
2589
2590 RefPtr<Label> end = generator.newLabel();
2591
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002592 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002593 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002594
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002595 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002596
2597 RefPtr<RegisterID> base = generator.newTemporary();
2598 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002599 RefPtr<RegisterID> enumerator;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002600 generator.emitNode(base.get(), m_expr);
2601 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002602 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002603
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002604 int profilerStartOffset = m_statement->startOffset();
2605 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002606
2607 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2608
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002609 // Indexed property loop.
2610 {
2611 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2612 RefPtr<Label> loopStart = generator.newLabel();
2613 RefPtr<Label> loopEnd = generator.newLabel();
2614
msaboff@apple.comb644c252015-03-24 10:05:21 +00002615 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002616 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2617 RefPtr<RegisterID> propertyName = generator.newTemporary();
2618
2619 generator.emitLabel(loopStart.get());
2620 generator.emitLoopHint();
2621
2622 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2623 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2624 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
2625 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2626
2627 generator.emitToIndexString(propertyName.get(), i.get());
2628 this->emitLoopHeader(generator, propertyName.get());
2629
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002630 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002631
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002632 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002633 generator.emitNode(dst, m_statement);
2634 generator.popIndexedForInScope(local.get());
2635
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002636 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002637
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002638 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002639 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002640 generator.emitInc(i.get());
2641 generator.emitJump(loopStart.get());
2642
2643 generator.emitLabel(scope->breakTarget());
2644 generator.emitJump(end.get());
2645 generator.emitLabel(loopEnd.get());
2646 }
2647
2648 // Structure property loop.
2649 {
2650 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2651 RefPtr<Label> loopStart = generator.newLabel();
2652 RefPtr<Label> loopEnd = generator.newLabel();
2653
msaboff@apple.comb644c252015-03-24 10:05:21 +00002654 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002655 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002656 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002657
2658 generator.emitLabel(loopStart.get());
2659 generator.emitLoopHint();
2660
2661 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2662 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002663 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002664 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2665
2666 this->emitLoopHeader(generator, propertyName.get());
2667
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002668 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002669
msaboff@apple.comb644c252015-03-24 10:05:21 +00002670 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002671 generator.emitNode(dst, m_statement);
2672 generator.popStructureForInScope(local.get());
2673
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002674 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002675
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002676 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002677 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002678 generator.emitInc(enumeratorIndex.get());
2679 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002680 generator.emitJump(loopStart.get());
2681
2682 generator.emitLabel(scope->breakTarget());
2683 generator.emitJump(end.get());
2684 generator.emitLabel(loopEnd.get());
2685 }
2686
2687 // Generic property loop.
2688 {
2689 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2690 RefPtr<Label> loopStart = generator.newLabel();
2691 RefPtr<Label> loopEnd = generator.newLabel();
2692
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002693 RefPtr<RegisterID> propertyName = generator.newTemporary();
2694
msaboff@apple.comb644c252015-03-24 10:05:21 +00002695 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002696
2697 generator.emitLabel(loopStart.get());
2698 generator.emitLoopHint();
2699
msaboff@apple.comb644c252015-03-24 10:05:21 +00002700 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2701 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2702
2703 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
2704 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2705
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002706 this->emitLoopHeader(generator, propertyName.get());
2707
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002708 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002709
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002710 generator.emitNode(dst, m_statement);
2711
2712 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002713 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002714 generator.emitInc(enumeratorIndex.get());
2715 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
2716 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002717
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002718 generator.emitLabel(scope->breakTarget());
2719 generator.emitJump(end.get());
2720 generator.emitLabel(loopEnd.get());
2721 }
2722
2723 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2724 generator.emitLabel(end.get());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002725 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002726 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002727}
2728
2729void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2730{
2731 this->emitMultiLoopBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002732}
2733
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002734// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002735void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2736{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002737 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002738 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002739 return;
2740 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002741
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002742 RegisterID* forLoopSymbolTable = nullptr;
sbarati@apple.combdbba812015-12-19 00:19:41 +00002743 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested, &forLoopSymbolTable);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002744 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002745 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002746 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002747 if (m_lexpr->isResolveNode()) {
2748 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002749 Variable var = generator.variable(ident);
2750 if (RegisterID* local = var.local())
2751 generator.emitMove(local, value);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002752 else {
2753 if (generator.isStrictMode())
2754 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002755 RegisterID* scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002756 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
sbarati@apple.come67fd782016-04-19 01:38:30 +00002757 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002758 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002759 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00002760 } else if (m_lexpr->isDotAccessorNode()) {
2761 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2762 const Identifier& ident = assignNode->identifier();
2763 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2764
2765 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002766 if (assignNode->base()->isSuperNode()) {
2767 RefPtr<RegisterID> thisValue = generator.ensureThis();
2768 generator.emitPutById(base.get(), thisValue.get(), ident, value);
2769 } else
2770 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002771 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002772 } else if (m_lexpr->isBracketAccessorNode()) {
2773 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
2774 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2775 RegisterID* subscript = generator.emitNode(assignNode->subscript());
2776
2777 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00002778 if (assignNode->base()->isSuperNode()) {
2779 RefPtr<RegisterID> thisValue = generator.ensureThis();
2780 generator.emitPutByVal(base.get(), thisValue.get(), subscript, value);
2781 } else
2782 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002783 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002784 } else {
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002785 ASSERT(m_lexpr->isDestructuringNode());
2786 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00002787 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002788 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002789 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002790 generator.emitNode(dst, m_statement);
2791 };
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002792 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
2793 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002794 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002795}
2796
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002797// ------------------------------ ContinueNode ---------------------------------
2798
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002799Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
2800{
2801 if (generator.shouldEmitDebugHooks())
2802 return 0;
2803
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002804 LabelScopePtr scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002805 ASSERT(scope);
2806
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002807 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002808 return 0;
2809
2810 return scope->continueTarget();
2811}
2812
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002813void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002814{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002815 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002816
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002817 LabelScopePtr scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002818 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002819
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002820 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002821 generator.emitJump(scope->continueTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002822
2823 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002824}
2825
2826// ------------------------------ BreakNode ------------------------------------
2827
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002828Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
2829{
2830 if (generator.shouldEmitDebugHooks())
2831 return 0;
2832
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002833 LabelScopePtr scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002834 ASSERT(scope);
2835
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002836 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002837 return 0;
2838
2839 return scope->breakTarget();
2840}
2841
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002842void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002843{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002844 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002845
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002846 LabelScopePtr scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002847 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002848
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002849 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002850 generator.emitJump(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002851
2852 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002853}
2854
2855// ------------------------------ ReturnNode -----------------------------------
2856
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002857void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002858{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002859 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002860 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002861
2862 if (dst == generator.ignoredResult())
2863 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002864
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002865 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00002866
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002867 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
saambarati1@gmail.com88b7e5b2015-08-05 21:45:20 +00002868 if (generator.isInFinallyBlock()) {
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002869 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002870 generator.emitPopScopes(generator.scopeRegister(), 0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002871 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002872
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002873 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002874 generator.emitReturn(returnRegister.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002875 generator.emitProfileControlFlow(endOffset());
2876 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
2877 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
2878 if (generator.vm()->controlFlowProfiler())
2879 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002880}
2881
2882// ------------------------------ WithNode -------------------------------------
2883
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002884void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002885{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002886 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.com170d6f22012-09-02 21:27:23 +00002887
2888 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002889 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002890 generator.emitPushWithScope(scope.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002891 generator.emitNodeInTailPosition(dst, m_statement);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002892 generator.emitPopWithScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002893}
2894
2895// ------------------------------ CaseClauseNode --------------------------------
2896
2897inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2898{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002899 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002900 if (!m_statements)
2901 return;
2902 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002903}
2904
2905// ------------------------------ CaseBlockNode --------------------------------
2906
2907enum SwitchKind {
2908 SwitchUnset = 0,
2909 SwitchNumber = 1,
2910 SwitchString = 2,
2911 SwitchNeither = 3
2912};
2913
2914static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2915{
2916 for (; list; list = list->getNext()) {
2917 ExpressionNode* clauseExpression = list->getClause()->expr();
2918 literalVector.append(clauseExpression);
2919 if (clauseExpression->isNumber()) {
2920 double value = static_cast<NumberNode*>(clauseExpression)->value();
2921 int32_t intVal = static_cast<int32_t>(value);
2922 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
2923 typeForTable = SwitchNeither;
2924 break;
2925 }
2926 if (intVal < min_num)
2927 min_num = intVal;
2928 if (intVal > max_num)
2929 max_num = intVal;
2930 typeForTable = SwitchNumber;
2931 continue;
2932 }
2933 if (clauseExpression->isString()) {
2934 if (typeForTable & ~SwitchString) {
2935 typeForTable = SwitchNeither;
2936 break;
2937 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00002938 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00002939 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00002940 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002941 if (intVal < min_num)
2942 min_num = intVal;
2943 if (intVal > max_num)
2944 max_num = intVal;
2945 }
2946 typeForTable = SwitchString;
2947 continue;
2948 }
2949 typeForTable = SwitchNeither;
2950 break;
2951 }
2952}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002953
2954static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002955{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002956 size_t length = 0;
2957 for (ClauseListNode* node = list1; node; node = node->getNext())
2958 ++length;
2959 for (ClauseListNode* node = list2; node; node = node->getNext())
2960 ++length;
2961 return length;
2962}
2963
2964SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2965{
2966 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
2967 return SwitchInfo::SwitchNone;
2968
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002969 SwitchKind typeForTable = SwitchUnset;
2970 bool singleCharacterSwitch = true;
2971
2972 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2973 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2974
2975 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2976 return SwitchInfo::SwitchNone;
2977
2978 if (typeForTable == SwitchNumber) {
2979 int32_t range = max_num - min_num;
2980 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2981 return SwitchInfo::SwitchImmediate;
2982 return SwitchInfo::SwitchNone;
2983 }
2984
2985 ASSERT(typeForTable == SwitchString);
2986
2987 if (singleCharacterSwitch) {
2988 int32_t range = max_num - min_num;
2989 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2990 return SwitchInfo::SwitchCharacter;
2991 }
2992
2993 return SwitchInfo::SwitchString;
2994}
2995
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002996void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002997{
2998 RefPtr<Label> defaultLabel;
2999 Vector<RefPtr<Label>, 8> labelVector;
3000 Vector<ExpressionNode*, 8> literalVector;
3001 int32_t min_num = std::numeric_limits<int32_t>::max();
3002 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00003003 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003004
3005 if (switchType != SwitchInfo::SwitchNone) {
3006 // Prepare the various labels
3007 for (uint32_t i = 0; i < literalVector.size(); i++)
3008 labelVector.append(generator.newLabel());
3009 defaultLabel = generator.newLabel();
3010 generator.beginSwitch(switchExpression, switchType);
3011 } else {
3012 // Setup jumps
3013 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3014 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3015 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3016 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3017 labelVector.append(generator.newLabel());
3018 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3019 }
3020
3021 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3022 RefPtr<RegisterID> clauseVal = generator.newTemporary();
3023 generator.emitNode(clauseVal.get(), list->getClause()->expr());
3024 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
3025 labelVector.append(generator.newLabel());
3026 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
3027 }
3028 defaultLabel = generator.newLabel();
3029 generator.emitJump(defaultLabel.get());
3030 }
3031
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003032 size_t i = 0;
3033 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
3034 generator.emitLabel(labelVector[i++].get());
3035 list->getClause()->emitBytecode(generator, dst);
3036 }
3037
3038 if (m_defaultClause) {
3039 generator.emitLabel(defaultLabel.get());
3040 m_defaultClause->emitBytecode(generator, dst);
3041 }
3042
3043 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
3044 generator.emitLabel(labelVector[i++].get());
3045 list->getClause()->emitBytecode(generator, dst);
3046 }
3047 if (!m_defaultClause)
3048 generator.emitLabel(defaultLabel.get());
3049
3050 ASSERT(i == labelVector.size());
3051 if (switchType != SwitchInfo::SwitchNone) {
3052 ASSERT(labelVector.size() == literalVector.size());
3053 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
3054 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003055}
3056
3057// ------------------------------ SwitchNode -----------------------------------
3058
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003059void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003060{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003061 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003062
oliver@apple.com6a976452013-03-11 21:02:39 +00003063 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003064
3065 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003066
sbarati@apple.combdbba812015-12-19 00:19:41 +00003067 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::DoNotOptimize, BytecodeGenerator::NestedScopeType::IsNested);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003068 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003069 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003070
3071 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003072 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003073}
3074
3075// ------------------------------ LabelNode ------------------------------------
3076
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003077void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003078{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003079 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003080
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00003081 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003082
oliver@apple.com6a976452013-03-11 21:02:39 +00003083 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00003084 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003085
3086 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003087}
3088
3089// ------------------------------ ThrowNode ------------------------------------
3090
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003091void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003092{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003093 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003094
3095 if (dst == generator.ignoredResult())
3096 dst = 0;
3097 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00003098 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003099 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003100
3101 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003102}
3103
3104// ------------------------------ TryNode --------------------------------------
3105
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003106void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003107{
3108 // NOTE: The catch and finally blocks must be labeled explicitly, so the
3109 // optimizer knows they may be jumped to from anywhere.
3110
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003111 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003112
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003113 ASSERT(m_catchBlock || m_finallyBlock);
3114
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003115 RefPtr<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003116 generator.emitLabel(tryStartLabel.get());
3117
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003118 if (m_finallyBlock)
3119 generator.pushFinallyContext(m_finallyBlock);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003120 TryData* tryData = generator.pushTry(tryStartLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003121
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003122 generator.emitNode(dst, m_tryBlock);
3123
3124 if (m_catchBlock) {
3125 RefPtr<Label> catchEndLabel = generator.newLabel();
3126
3127 // Normal path: jump over the catch block.
3128 generator.emitJump(catchEndLabel.get());
3129
3130 // Uncaught exception path: the catch block.
3131 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003132 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
3133 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
3134 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), here.get(), HandlerType::Catch);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003135
3136 if (m_finallyBlock) {
3137 // If the catch block throws an exception and we have a finally block, then the finally
3138 // block should "catch" that exception.
3139 tryData = generator.pushTry(here.get());
3140 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00003141
utatane.tea@gmail.com08fe3112016-01-22 04:21:36 +00003142 generator.emitPushCatchScope(m_lexicalVariables);
3143 m_catchPattern->bindValue(generator, thrownValueRegister.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003144 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003145 if (m_finallyBlock)
3146 generator.emitNode(dst, m_catchBlock);
3147 else
3148 generator.emitNodeInTailPosition(dst, m_catchBlock);
msaboff@apple.com78461ac2016-06-02 04:07:14 +00003149 generator.emitLoad(thrownValueRegister.get(), jsUndefined());
sbarati@apple.com62be0b02015-09-19 15:36:46 +00003150 generator.emitPopCatchScope(m_lexicalVariables);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003151 generator.emitLabel(catchEndLabel.get());
3152 }
3153
3154 if (m_finallyBlock) {
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00003155 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
3156
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003157 generator.popFinallyContext();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003158
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003159 RefPtr<Label> finallyEndLabel = generator.newLabel();
3160
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003161 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003162
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00003163 // Normal path: run the finally code, and jump to the end.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003164 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003165 generator.emitNodeInTailPosition(dst, m_finallyBlock);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003166 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003167 generator.emitJump(finallyEndLabel.get());
3168
3169 // Uncaught exception path: invoke the finally block, then re-throw the exception.
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003170 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
3171 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
3172 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003173 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00003174 generator.emitNodeInTailPosition(dst, m_finallyBlock);
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00003175 generator.emitThrow(exceptionRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003176
3177 generator.emitLabel(finallyEndLabel.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003178 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00003179 } else
saambarati1@gmail.com15952502015-02-23 22:10:51 +00003180 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003181
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003182}
3183
3184// ------------------------------ ScopeNode -----------------------------
3185
3186inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
3187{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003188 if (!m_statements)
3189 return;
3190 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003191}
3192
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003193static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
3194{
3195 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
3196
3197 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3198 generator.emitLoad(dstRegister.get(), jsUndefined());
3199 generator.emitProfileControlFlow(scopeNode.startStartOffset());
3200 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
3201
3202 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
3203 generator.emitEnd(dstRegister.get());
3204}
3205
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003206// ------------------------------ ProgramNode -----------------------------
3207
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003208void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003209{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003210 emitProgramNodeBytecode(generator, *this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003211}
3212
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003213// ------------------------------ ModuleProgramNode --------------------
3214
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003215void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003216{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003217 emitProgramNodeBytecode(generator, *this);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003218}
3219
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003220// ------------------------------ EvalNode -----------------------------
3221
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00003222void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003223{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003224 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003225
3226 RefPtr<RegisterID> dstRegister = generator.newTemporary();
3227 generator.emitLoad(dstRegister.get(), jsUndefined());
3228 emitStatementsBytecode(generator, dstRegister.get());
3229
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003230 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003231 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003232}
3233
ggaren@apple.come7afe402015-08-10 20:24:35 +00003234// ------------------------------ FunctionNode -----------------------------
ggaren@apple.com6f851d72014-12-04 23:47:49 +00003235
3236void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003237{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00003238 if (generator.vm()->typeProfiler()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003239 for (size_t i = 0; i < m_parameters->size(); i++) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003240 // Destructuring parameters are handled in destructuring nodes.
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00003241 if (!m_parameters->at(i).first->isBindingNode())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003242 continue;
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00003243 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003244 RegisterID reg(CallFrame::argumentOffset(i));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003245 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00003246 }
3247 }
3248
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00003249 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00003250 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003251
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003252 switch (generator.parseMode()) {
3253 case SourceParseMode::GeneratorWrapperFunctionMode: {
3254 StatementNode* singleStatement = this->singleStatement();
3255 ASSERT(singleStatement->isExprStatement());
3256 ExprStatementNode* exprStatement = static_cast<ExprStatementNode*>(singleStatement);
3257 ExpressionNode* expr = exprStatement->expr();
3258 ASSERT(expr->isFuncExprNode());
3259 FuncExprNode* funcExpr = static_cast<FuncExprNode*>(expr);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003260
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003261 RefPtr<RegisterID> next = generator.newTemporary();
3262 generator.emitNode(next.get(), funcExpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003263
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003264 if (generator.superBinding() == SuperBinding::Needed) {
3265 RefPtr<RegisterID> homeObject = emitHomeObjectForCallee(generator);
3266 emitPutHomeObject(generator, next.get(), homeObject.get());
3267 }
3268
3269 // FIXME: Currently, we just create an object and store generator related fields as its properties for ease.
3270 // But to make it efficient, we will introduce JSGenerator class, add opcode new_generator and use its C++ fields instead of these private properties.
3271 // https://bugs.webkit.org/show_bug.cgi?id=151545
3272
3273 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().generatorNextPrivateName, next.get(), PropertyNode::KnownDirect);
3274
3275 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().generatorThisPrivateName, generator.thisRegister(), PropertyNode::KnownDirect);
3276
3277 RegisterID* initialState = generator.emitLoad(nullptr, jsNumber(0));
3278 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().generatorStatePrivateName, initialState, PropertyNode::KnownDirect);
3279
3280 generator.emitDirectPutById(generator.generatorRegister(), generator.propertyNames().generatorFramePrivateName, generator.emitLoad(nullptr, jsNull()), PropertyNode::KnownDirect);
3281
mark.lam@apple.comfa35e782013-11-19 21:55:16 +00003282 ASSERT(startOffset() >= lineStartOffset());
3283 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003284 generator.emitReturn(generator.generatorRegister());
3285 break;
3286 }
3287
3288 case SourceParseMode::GeneratorBodyMode: {
3289 RefPtr<Label> generatorBodyLabel = generator.newLabel();
3290 {
3291 RefPtr<RegisterID> condition = generator.newTemporary();
3292 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode))));
3293 generator.emitJumpIfTrue(condition.get(), generatorBodyLabel.get());
3294
3295 RefPtr<Label> throwLabel = generator.newLabel();
3296 generator.emitEqualityOp(op_stricteq, condition.get(), generator.generatorResumeModeRegister(), generator.emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode))));
3297 generator.emitJumpIfTrue(condition.get(), throwLabel.get());
3298
3299 generator.emitReturn(generator.generatorValueRegister());
3300
3301 generator.emitLabel(throwLabel.get());
3302 generator.emitThrow(generator.generatorValueRegister());
3303 }
3304
3305 generator.emitLabel(generatorBodyLabel.get());
3306
3307 emitStatementsBytecode(generator, generator.ignoredResult());
3308
3309 RefPtr<Label> done = generator.newLabel();
3310 generator.emitLabel(done.get());
3311 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
3312 generator.endGenerator(done.get());
3313 break;
3314 }
3315
3316 default: {
3317 emitStatementsBytecode(generator, generator.ignoredResult());
3318
3319 StatementNode* singleStatement = this->singleStatement();
3320 ReturnNode* returnNode = 0;
3321
3322 // Check for a return statement at the end of a function composed of a single block.
3323 if (singleStatement && singleStatement->isBlock()) {
3324 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
3325 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
3326 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
3327 }
3328
3329 // If there is no return we must automatically insert one.
3330 if (!returnNode) {
gskachkov@gmail.com78667862016-03-01 21:28:45 +00003331 if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext() && generator.isSuperCallUsedInInnerArrowFunction())
commit-queue@webkit.orgb2610c02015-12-08 20:24:04 +00003332 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
3333
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003334 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
3335 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
3336 ASSERT(startOffset() >= lineStartOffset());
3337 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
3338 generator.emitReturn(r0);
3339 return;
3340 }
3341 break;
3342 }
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00003343 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003344}
3345
3346// ------------------------------ FuncDeclNode ---------------------------------
3347
sbarati@apple.come86176c2016-04-07 21:01:42 +00003348void FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003349{
sbarati@apple.come86176c2016-04-07 21:01:42 +00003350 generator.hoistSloppyModeFunctionIfNecessary(metadata()->ident());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003351}
3352
3353// ------------------------------ FuncExprNode ---------------------------------
3354
3355RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3356{
3357 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3358}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003359
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00003360// ------------------------------ ArrowFuncExprNode ---------------------------------
3361
3362RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3363{
3364 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3365}
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003366
mark.lam@apple.com43137872016-03-17 14:58:57 +00003367// ------------------------------ MethodDefinitionNode ---------------------------------
3368
3369RegisterID* MethodDefinitionNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3370{
3371 return generator.emitNewMethodDefinition(generator.finalDestination(dst), this);
3372}
3373
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003374// ------------------------------ YieldExprNode --------------------------------
3375
3376RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3377{
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003378 if (!delegate()) {
3379 RefPtr<RegisterID> arg = nullptr;
3380 if (argument()) {
3381 arg = generator.newTemporary();
3382 generator.emitNode(arg.get(), argument());
3383 } else
3384 arg = generator.emitLoad(nullptr, jsUndefined());
3385 RefPtr<RegisterID> value = generator.emitYield(arg.get());
3386 if (dst == generator.ignoredResult())
3387 return nullptr;
3388 return generator.emitMove(generator.finalDestination(dst), value.get());
3389 }
3390 RefPtr<RegisterID> arg = generator.newTemporary();
3391 generator.emitNode(arg.get(), argument());
3392 RefPtr<RegisterID> value = generator.emitDelegateYield(arg.get(), this);
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003393 if (dst == generator.ignoredResult())
utatane.tea@gmail.comfdd9bf42015-12-02 03:16:28 +00003394 return nullptr;
3395 return generator.emitMove(generator.finalDestination(dst), value.get());
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003396}
3397
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003398// ------------------------------ ClassDeclNode ---------------------------------
3399
3400void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3401{
3402 generator.emitNode(dst, m_classDeclaration);
3403}
3404
3405// ------------------------------ ClassExprNode ---------------------------------
3406
3407RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3408{
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003409 if (!m_name.isNull())
sbarati@apple.combdbba812015-12-19 00:19:41 +00003410 generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003411
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003412 RefPtr<RegisterID> superclass;
3413 if (m_classHeritage) {
3414 superclass = generator.newTemporary();
3415 generator.emitNode(superclass.get(), m_classHeritage);
3416 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003417
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003418 RefPtr<RegisterID> constructor;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003419
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003420 // FIXME: Make the prototype non-configurable & non-writable.
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003421 if (m_constructorExpression) {
3422 ASSERT(m_constructorExpression->isFuncExprNode());
3423 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata();
3424 metadata->setEcmaName(ecmaName());
3425 metadata->setClassSource(m_classSource);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003426 constructor = generator.emitNode(dst, m_constructorExpression);
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003427 } else {
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003428 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
mark.lam@apple.com4b79ce72016-03-11 21:08:08 +00003429 m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base,
3430 m_name, ecmaName(), m_classSource);
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003431 }
3432
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003433 const auto& propertyNames = generator.propertyNames();
3434 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003435
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003436 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003437 RefPtr<RegisterID> protoParent = generator.newTemporary();
3438 generator.emitLoad(protoParent.get(), jsNull());
3439
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003440 RefPtr<RegisterID> tempRegister = generator.newTemporary();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003441
3442 // FIXME: Throw TypeError if it's a generator function.
3443 RefPtr<Label> superclassIsUndefinedLabel = generator.newLabel();
3444 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
3445
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003446 RefPtr<Label> superclassIsNullLabel = generator.newLabel();
3447 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3448
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003449 RefPtr<Label> superclassIsObjectLabel = generator.newLabel();
3450 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003451 generator.emitLabel(superclassIsUndefinedLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003452 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3453 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003454 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
3455
3456 RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
3457 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
keith_miller@apple.com02373132016-01-14 20:45:48 +00003458 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_function, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
3459 generator.emitThrowTypeError(ASCIILiteral("The value of the superclass's prototype property is not an object."));
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003460 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
3461
3462 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003463 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003464 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
3465
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003466 emitPutHomeObject(generator, constructor.get(), prototype.get());
3467 }
3468
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003469 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.constructor);
3470 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
3471 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
3472
3473 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.prototype);
3474 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
3475
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003476 if (m_staticMethods)
3477 generator.emitNode(constructor.get(), m_staticMethods);
3478
3479 if (m_instanceMethods)
3480 generator.emitNode(prototype.get(), m_instanceMethods);
3481
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003482 if (!m_name.isNull()) {
3483 Variable classNameVar = generator.variable(m_name);
3484 RELEASE_ASSERT(classNameVar.isResolved());
3485 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
sbarati@apple.come67fd782016-04-19 01:38:30 +00003486 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, InitializationMode::Initialization);
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003487 generator.popLexicalScope(this);
3488 }
3489
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003490 return generator.moveToDestinationIfNeeded(dst, constructor.get());
3491}
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003492
3493// ------------------------------ ImportDeclarationNode -----------------------
3494
3495void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3496{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003497 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003498}
3499
3500// ------------------------------ ExportAllDeclarationNode --------------------
3501
3502void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3503{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003504 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003505}
3506
3507// ------------------------------ ExportDefaultDeclarationNode ----------------
3508
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003509void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003510{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003511 ASSERT(m_declaration);
3512 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003513}
3514
3515// ------------------------------ ExportLocalDeclarationNode ------------------
3516
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003517void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003518{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003519 ASSERT(m_declaration);
3520 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003521}
3522
3523// ------------------------------ ExportNamedDeclarationNode ------------------
3524
3525void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3526{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003527 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003528}
3529
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003530// ------------------------------ DestructuringAssignmentNode -----------------
3531RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
oliver@apple.comd055db62013-10-02 19:11:04 +00003532{
3533 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
3534 return result;
3535 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
3536 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00003537 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003538 return generator.moveToDestinationIfNeeded(dst, initializer.get());
3539}
3540
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003541static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
3542{
3543 ASSERT(defaultValue);
3544 RefPtr<Label> isNotUndefined = generator.newLabel();
3545 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
3546 generator.emitNode(maybeUndefined, defaultValue);
3547 generator.emitLabel(isNotUndefined.get());
3548}
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003549
oliver@apple.com47784d62013-10-25 21:31:36 +00003550void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003551{
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003552 RefPtr<RegisterID> iterator = generator.newTemporary();
3553 {
3554 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
3555 CallArguments args(generator, nullptr);
3556 generator.emitMove(args.thisRegister(), rhs);
3557 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
3558 }
3559
utatane.tea@gmail.coma5c94332015-06-23 00:51:44 +00003560 if (m_targetPatterns.isEmpty()) {
3561 generator.emitIteratorClose(iterator.get(), this);
3562 return;
3563 }
3564
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003565 RefPtr<RegisterID> done;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003566 for (auto& target : m_targetPatterns) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003567 switch (target.bindingType) {
3568 case BindingType::Elision:
3569 case BindingType::Element: {
3570 RefPtr<Label> iterationSkipped = generator.newLabel();
3571 if (!done)
3572 done = generator.newTemporary();
3573 else
3574 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003575
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003576 RefPtr<RegisterID> value = generator.newTemporary();
3577 generator.emitIteratorNext(value.get(), iterator.get(), this);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003578 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003579 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
3580 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003581
3582 {
3583 RefPtr<Label> valueIsSet = generator.newLabel();
3584 generator.emitJump(valueIsSet.get());
3585 generator.emitLabel(iterationSkipped.get());
3586 generator.emitLoad(value.get(), jsUndefined());
3587 generator.emitLabel(valueIsSet.get());
3588 }
3589
3590 if (target.bindingType == BindingType::Element) {
3591 if (target.defaultValue)
3592 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
3593 target.pattern->bindValue(generator, value.get());
3594 }
3595 break;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003596 }
3597
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003598 case BindingType::RestElement: {
3599 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
3600
3601 RefPtr<Label> iterationDone = generator.newLabel();
3602 if (!done)
3603 done = generator.newTemporary();
3604 else
3605 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3606
3607 RefPtr<RegisterID> index = generator.newTemporary();
3608 generator.emitLoad(index.get(), jsNumber(0));
3609 RefPtr<Label> loopStart = generator.newLabel();
3610 generator.emitLabel(loopStart.get());
3611
3612 RefPtr<RegisterID> value = generator.newTemporary();
3613 generator.emitIteratorNext(value.get(), iterator.get(), this);
3614 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
3615 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3616 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
3617
3618 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
3619 generator.emitInc(index.get());
3620 generator.emitJump(loopStart.get());
3621
3622 generator.emitLabel(iterationDone.get());
3623 target.pattern->bindValue(generator, array.get());
3624 break;
3625 }
3626 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003627 }
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003628
3629 RefPtr<Label> iteratorClosed = generator.newLabel();
3630 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
3631 generator.emitIteratorClose(iterator.get(), this);
3632 generator.emitLabel(iteratorClosed.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003633}
3634
3635RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
3636{
oliver@apple.comd055db62013-10-02 19:11:04 +00003637 if (!rhs->isSimpleArray())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003638 return nullptr;
3639
3640 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
3641 Vector<ExpressionNode*> elements;
3642 for (; elementNodes; elementNodes = elementNodes->next()) {
3643 ExpressionNode* value = elementNodes->value();
3644 if (value->isSpreadExpression())
3645 return nullptr;
3646 elements.append(value);
3647 }
oliver@apple.com47784d62013-10-25 21:31:36 +00003648
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003649 RefPtr<RegisterID> resultRegister;
3650 if (dst && dst != generator.ignoredResult())
3651 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00003652 if (m_targetPatterns.size() != elements.size())
fpizlo@apple.com1d81e2e2016-02-09 20:18:31 +00003653 return nullptr;
oliver@apple.comd055db62013-10-02 19:11:04 +00003654 Vector<RefPtr<RegisterID>> registers;
3655 registers.reserveCapacity(m_targetPatterns.size());
3656 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3657 registers.uncheckedAppend(generator.newTemporary());
3658 generator.emitNode(registers.last().get(), elements[i]);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003659 if (m_targetPatterns[i].defaultValue)
3660 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003661 if (resultRegister)
3662 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003663 }
3664
3665 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003666 if (m_targetPatterns[i].pattern)
3667 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003668 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003669 if (resultRegister)
3670 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00003671 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00003672}
3673
3674void ArrayPatternNode::toString(StringBuilder& builder) const
3675{
3676 builder.append('[');
3677 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003678 const auto& target = m_targetPatterns[i];
3679
3680 switch (target.bindingType) {
3681 case BindingType::Elision:
oliver@apple.comd055db62013-10-02 19:11:04 +00003682 builder.append(',');
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003683 break;
3684
3685 case BindingType::Element:
3686 target.pattern->toString(builder);
3687 if (i < m_targetPatterns.size() - 1)
3688 builder.append(',');
3689 break;
3690
3691 case BindingType::RestElement:
3692 builder.append("...");
3693 target.pattern->toString(builder);
3694 break;
oliver@apple.comd055db62013-10-02 19:11:04 +00003695 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003696 }
3697 builder.append(']');
3698}
3699
3700void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3701{
3702 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.comc497d152015-07-17 18:48:30 +00003703 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
oliver@apple.comd055db62013-10-02 19:11:04 +00003704 node->collectBoundIdentifiers(identifiers);
3705 }
3706}
3707
3708void ObjectPatternNode::toString(StringBuilder& builder) const
3709{
3710 builder.append('{');
3711 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003712 if (m_targetPatterns[i].wasString)
akling@apple.coma9904fb2015-05-08 08:44:23 +00003713 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003714 else
oliver@apple.comd055db62013-10-02 19:11:04 +00003715 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00003716 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00003717 m_targetPatterns[i].pattern->toString(builder);
3718 if (i < m_targetPatterns.size() - 1)
3719 builder.append(',');
3720 }
3721 builder.append('}');
3722}
3723
oliver@apple.com47784d62013-10-25 21:31:36 +00003724void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003725{
commit-queue@webkit.org4d3e0c22015-12-01 20:11:20 +00003726 generator.emitRequireObjectCoercible(rhs, ASCIILiteral("Right side of assignment cannot be destructured"));
oliver@apple.comd055db62013-10-02 19:11:04 +00003727 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3728 auto& target = m_targetPatterns[i];
3729 RefPtr<RegisterID> temp = generator.newTemporary();
utatane.tea@gmail.com109ad312015-12-14 02:52:51 +00003730 if (!target.propertyExpression) {
3731 // Should not emit get_by_id for indexed ones.
3732 Optional<uint32_t> optionalIndex = parseIndex(target.propertyName);
3733 if (!optionalIndex)
3734 generator.emitGetById(temp.get(), rhs, target.propertyName);
3735 else {
3736 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
3737 generator.emitGetByVal(temp.get(), rhs, index.get());
3738 }
3739 } else {
commit-queue@webkit.org38980282015-11-25 01:43:14 +00003740 RefPtr<RegisterID> propertyName = generator.emitNode(target.propertyExpression);
3741 generator.emitGetByVal(temp.get(), rhs, propertyName.get());
3742 }
3743
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003744 if (target.defaultValue)
3745 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
oliver@apple.com47784d62013-10-25 21:31:36 +00003746 target.pattern->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003747 }
3748}
3749
3750void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3751{
3752 for (size_t i = 0; i < m_targetPatterns.size(); i++)
3753 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
3754}
3755
oliver@apple.com47784d62013-10-25 21:31:36 +00003756void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003757{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003758 Variable var = generator.variable(m_boundProperty);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003759 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003760 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003761 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3762 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003763 if (isReadOnly) {
3764 generator.emitReadOnlyExceptionIfNeeded(var);
3765 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00003766 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003767 generator.emitMove(local, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003768 generator.emitProfileType(local, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003769 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003770 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003771 return;
3772 }
3773 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003774 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003775 RegisterID* scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003776 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003777 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3778 generator.emitTDZCheckIfNecessary(var, nullptr, scope);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003779 if (isReadOnly) {
3780 generator.emitReadOnlyExceptionIfNeeded(var);
3781 return;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003782 }
sbarati@apple.come67fd782016-04-19 01:38:30 +00003783 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, initializationModeForAssignmentContext(m_bindingContext));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003784 generator.emitProfileType(value, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003785 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003786 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003787 return;
3788}
3789
3790void BindingNode::toString(StringBuilder& builder) const
3791{
3792 builder.append(m_boundProperty.string());
3793}
3794
3795void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3796{
3797 identifiers.append(m_boundProperty);
3798}
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003799
3800void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
3801{
3802}
3803
3804void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
3805{
3806 if (m_assignmentTarget->isResolveNode()) {
3807 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
3808 Variable var = generator.variable(lhs->identifier());
3809 bool isReadOnly = var.isReadOnly();
3810 if (RegisterID* local = var.local()) {
3811 generator.emitTDZCheckIfNecessary(var, local, nullptr);
3812
3813 if (isReadOnly)
3814 generator.emitReadOnlyExceptionIfNeeded(var);
3815 else {
3816 generator.invalidateForInContextForLocal(local);
3817 generator.moveToDestinationIfNeeded(local, value);
3818 generator.emitProfileType(local, divotStart(), divotEnd());
3819 }
3820 return;
3821 }
3822 if (generator.isStrictMode())
3823 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3824 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
3825 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
3826 if (isReadOnly) {
3827 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
3828 if (threwException)
3829 return;
3830 }
3831 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3832 if (!isReadOnly) {
sbarati@apple.come67fd782016-04-19 01:38:30 +00003833 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::NotInitialization);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003834 generator.emitProfileType(value, var, divotStart(), divotEnd());
3835 }
3836 } else if (m_assignmentTarget->isDotAccessorNode()) {
3837 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
3838 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
3839 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003840 if (lhs->base()->isSuperNode()) {
3841 RefPtr<RegisterID> thisValue = generator.ensureThis();
3842 generator.emitPutById(base.get(), thisValue.get(), lhs->identifier(), value);
3843 } else
3844 generator.emitPutById(base.get(), lhs->identifier(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003845 generator.emitProfileType(value, divotStart(), divotEnd());
3846 } else if (m_assignmentTarget->isBracketAccessorNode()) {
3847 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
3848 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
3849 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(lhs->subscript(), true, false);
3850 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
sbarati@apple.com23315d62016-05-09 20:17:23 +00003851 if (lhs->base()->isSuperNode()) {
3852 RefPtr<RegisterID> thisValue = generator.ensureThis();
3853 generator.emitPutByVal(base.get(), thisValue.get(), property.get(), value);
3854 } else
3855 generator.emitPutByVal(base.get(), property.get(), value);
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003856 generator.emitProfileType(value, divotStart(), divotEnd());
3857 }
3858}
3859
3860void AssignmentElementNode::toString(StringBuilder& builder) const
3861{
3862 if (m_assignmentTarget->isResolveNode())
3863 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
3864}
3865
sbarati@apple.comc0722da2015-11-20 02:37:47 +00003866void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3867{
3868 identifiers.append(m_name);
3869}
3870void RestParameterNode::toString(StringBuilder& builder) const
3871{
3872 builder.append(m_name.string());
3873}
3874void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
3875{
3876 RELEASE_ASSERT_NOT_REACHED();
3877}
3878void RestParameterNode::emit(BytecodeGenerator& generator)
3879{
3880 Variable var = generator.variable(m_name);
3881 if (RegisterID* local = var.local()) {
3882 generator.emitRestParameter(local, m_numParametersToSkip);
3883 generator.emitProfileType(local, var, m_divotStart, m_divotEnd);
3884 return;
3885 }
3886
sbarati@apple.com855d5602015-11-30 20:36:54 +00003887 RefPtr<RegisterID> restParameterArray = generator.newTemporary();
3888 generator.emitRestParameter(restParameterArray.get(), m_numParametersToSkip);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00003889 generator.emitProfileType(restParameterArray.get(), var, m_divotStart, m_divotEnd);
3890 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
3891 generator.emitExpressionInfo(m_divotEnd, m_divotStart, m_divotEnd);
sbarati@apple.come67fd782016-04-19 01:38:30 +00003892 generator.emitPutToScope(scope.get(), var, restParameterArray.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, InitializationMode::Initialization);
sbarati@apple.comc0722da2015-11-20 02:37:47 +00003893}
3894
3895
oliver@apple.com72f8a822013-10-17 01:02:34 +00003896RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3897{
3898 RELEASE_ASSERT_NOT_REACHED();
3899 return 0;
3900}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003901
3902} // namespace JSC