blob: 9b34643021ce726bd383cf4a5d5621121ba5b7e3 [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)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013, 2015 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"
37#include "JSGlobalObject.h"
oliver@apple.comd055db62013-10-02 19:11:04 +000038#include "JSONObject.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000039#include "LabelScope.h"
40#include "Lexer.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000041#include "JSCInlines.h"
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +000042#include "JSTemplateRegistryKey.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000043#include "Parser.h"
44#include "PropertyNameArray.h"
zherczeg@webkit.org17dc93a2010-06-22 19:16:57 +000045#include "RegExpCache.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000046#include "RegExpObject.h"
47#include "SamplingTool.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{
rniwa@webkit.orge8caec42015-03-31 19:42:56 +0000148 if (m_shouldAlwaysEmitTDZCheck || generator.constructorKind() == ConstructorKind::Derived)
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000149 generator.emitTDZCheck(generator.thisRegister());
150
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000151 if (dst == generator.ignoredResult())
152 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000153
154 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000155 static const unsigned thisLength = 4;
156 generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000157 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000158}
159
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000160// ------------------------------ SuperNode -------------------------------------
161
162RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
163{
164 if (dst == generator.ignoredResult())
165 return 0;
166
167 RegisterID callee;
168 callee.setIndex(JSStack::Callee);
169
170 RefPtr<RegisterID> homeObject = generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
171 RefPtr<RegisterID> protoParent = generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
172 return generator.emitGetById(generator.finalDestination(dst), protoParent.get(), generator.propertyNames().constructor);
173}
174
175static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
176{
177 RegisterID callee;
178 callee.setIndex(JSStack::Callee);
179
180 RefPtr<RegisterID> homeObject = generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
181 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
182}
183
commit-queue@webkit.org17f99e42015-07-21 18:18:42 +0000184// ------------------------------ NewTargetNode ----------------------------------
185
186RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
187{
188 if (dst == generator.ignoredResult())
189 return nullptr;
190
191 return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
192}
193
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000194// ------------------------------ ResolveNode ----------------------------------
195
196bool ResolveNode::isPure(BytecodeGenerator& generator) const
197{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000198 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000199}
200
201RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
202{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000203 Variable var = generator.variable(m_ident);
204 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000205 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000206 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000207 return nullptr;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000208
209 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000210 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000211 }
212
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000213 JSTextPosition divot = m_start + m_ident.length();
214 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000215 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000216 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000217 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000218 generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000219 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000220 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000221}
222
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000223#if ENABLE(ES6_TEMPLATE_LITERAL_SYNTAX)
224// ------------------------------ TemplateStringNode -----------------------------------
225
226RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
227{
228 if (dst == generator.ignoredResult())
229 return nullptr;
230 return generator.emitLoad(dst, JSValue(generator.addStringConstant(cooked())));
231}
232
233// ------------------------------ TemplateLiteralNode -----------------------------------
234
235RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
236{
237 if (!m_templateExpressions) {
238 TemplateStringNode* templateString = m_templateStrings->value();
239 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
240 return generator.emitNode(dst, templateString);
241 }
242
243 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
244
245 TemplateStringListNode* templateString = m_templateStrings;
246 TemplateExpressionListNode* templateExpression = m_templateExpressions;
247 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
248 // Evaluate TemplateString.
249 if (!templateString->value()->cooked().isEmpty()) {
250 temporaryRegisters.append(generator.newTemporary());
251 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
252 }
253
254 // Evaluate Expression.
255 temporaryRegisters.append(generator.newTemporary());
256 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
257 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
258 }
259
260 // Evaluate tail TemplateString.
261 if (!templateString->value()->cooked().isEmpty()) {
262 temporaryRegisters.append(generator.newTemporary());
263 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
264 }
265
266 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
267}
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000268
269// ------------------------------ TaggedTemplateNode -----------------------------------
270
271RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
272{
273 ExpectedFunction expectedFunction = NoExpectedFunction;
274 RefPtr<RegisterID> tag = nullptr;
275 RefPtr<RegisterID> base = nullptr;
276 if (!m_tag->isLocation()) {
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000277 tag = generator.newTemporary();
278 tag = generator.emitNode(tag.get(), m_tag);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000279 } else if (m_tag->isResolveNode()) {
280 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
281 const Identifier& identifier = resolve->identifier();
282 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
283
284 Variable var = generator.variable(identifier);
285 if (RegisterID* local = var.local())
286 tag = generator.emitMove(generator.newTemporary(), local);
287 else {
288 tag = generator.newTemporary();
289 base = generator.newTemporary();
290
291 JSTextPosition newDivot = divotStart() + identifier.length();
292 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
293 generator.moveToDestinationIfNeeded(base.get(), generator.emitResolveScope(base.get(), var));
294 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
295 }
296 } else if (m_tag->isBracketAccessorNode()) {
297 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000298 base = generator.newTemporary();
299 base = generator.emitNode(base.get(), bracket->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000300 RefPtr<RegisterID> property = generator.emitNode(bracket->subscript());
301 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
302 } else {
303 ASSERT(m_tag->isDotAccessorNode());
304 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000305 base = generator.newTemporary();
306 base = generator.emitNode(base.get(), dot->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000307 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
308 }
309
310 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(generator.newTemporary(), this);
311
312 unsigned expressionsCount = 0;
313 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
314 ++expressionsCount;
315
316 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
317 if (base)
318 generator.emitMove(callArguments.thisRegister(), base.get());
319 else
320 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
321
322 unsigned argumentIndex = 0;
323 generator.emitMove(callArguments.argumentRegister(argumentIndex++), templateObject.get());
324 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
325 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
326
327 return generator.emitCall(generator.finalDestination(dst, tag.get()), tag.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
328}
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000329#endif
330
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000331// ------------------------------ ArrayNode ------------------------------------
332
333RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
334{
335 // FIXME: Should we put all of this code into emitNewArray?
336
337 unsigned length = 0;
338 ElementNode* firstPutElement;
339 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000340 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000341 break;
342 ++length;
343 }
344
345 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000346 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000347
oliver@apple.coma991d692011-06-14 23:39:25 +0000348 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000349 ElementNode* n = firstPutElement;
350 for (; n; n = n->next()) {
351 if (n->value()->isSpreadExpression())
352 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000353 RegisterID* value = generator.emitNode(n->value());
354 length += n->elision();
355 generator.emitPutByIndex(array.get(), length++, value);
356 }
357
358 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000359 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000360 generator.emitPutById(array.get(), generator.propertyNames().length, value);
361 }
362
363 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000364
365handleSpread:
366 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
367 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
368 {
oliver@apple.come050d642013-10-19 00:09:28 +0000369 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000370 generator.emitInc(index.get());
371 };
372 for (; n; n = n->next()) {
373 if (n->elision())
374 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
375 if (n->value()->isSpreadExpression()) {
376 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
377 generator.emitEnumeration(spread, spread->expression(), spreader);
378 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000379 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000380 generator.emitInc(index.get());
381 }
382 }
383
384 if (m_elision) {
385 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
386 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
387 }
388 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000389}
390
391bool ArrayNode::isSimpleArray() const
392{
393 if (m_elision || m_optional)
394 return false;
395 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
396 if (ptr->elision())
397 return false;
398 }
399 return true;
400}
401
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000402ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000403{
404 ASSERT(!m_elision && !m_optional);
405 ElementNode* ptr = m_element;
406 if (!ptr)
407 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000408 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000409 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000410 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000411 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000412 ArgumentListNode* tail = head;
413 ptr = ptr->next();
414 for (; ptr; ptr = ptr->next()) {
415 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000416 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000417 }
418 return head;
419}
420
421// ------------------------------ ObjectLiteralNode ----------------------------
422
423RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
424{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000425 if (!m_list) {
426 if (dst == generator.ignoredResult())
427 return 0;
428 return generator.emitNewObject(generator.finalDestination(dst));
429 }
430 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
431 generator.emitNode(newObj.get(), m_list);
432 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000433}
434
435// ------------------------------ PropertyListNode -----------------------------
436
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000437static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
438{
439 generator.emitPutById(function, generator.propertyNames().homeObjectPrivateName, homeObject);
440}
441
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000442RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
443{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000444 // Fast case: this loop just handles regular value properties.
445 PropertyListNode* p = this;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000446 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000447 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000448
449 // Were there any get/set properties?
450 if (p) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000451 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
452 // a computed property, just emit everything as that may override previous values.
453 bool hasComputedProperty = false;
454
barraclough@apple.com09a55682012-01-30 18:28:39 +0000455 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000456 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000457 GetterSetterMap map;
458
459 // Build a map, pairing get/set values together.
460 for (PropertyListNode* q = p; q; q = q->m_next) {
461 PropertyNode* node = q->m_node;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000462 if (node->m_type & PropertyNode::Computed) {
463 hasComputedProperty = true;
464 break;
465 }
466 if (node->m_type & PropertyNode::Constant)
barraclough@apple.com09a55682012-01-30 18:28:39 +0000467 continue;
468
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000469 // Duplicates are possible.
470 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
oliver@apple.com72d38322013-10-21 19:23:24 +0000471 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000472 if (!result.isNewEntry) {
473 if (result.iterator->value.first->m_type == node->m_type)
474 result.iterator->value.first = node;
475 else
476 result.iterator->value.second = node;
477 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000478 }
479
480 // Iterate over the remaining properties in the list.
481 for (; p; p = p->m_next) {
482 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000483
484 // Handle regular values.
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000485 if (node->m_type & PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000486 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000487 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000488 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000489
oliver@apple.com72d38322013-10-21 19:23:24 +0000490 RegisterID* value = generator.emitNode(node->m_assign);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000491 bool isClassProperty = node->needsSuperBinding();
492 if (isClassProperty)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000493 emitPutHomeObject(generator, value, dst);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000494
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000495 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
496
497 // This is a get/set property which may be overridden by a computed property later.
498 if (hasComputedProperty) {
499 if (node->m_type & PropertyNode::Getter)
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +0000500 generator.emitPutGetterById(dst, *node->name(), Accessor, value);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000501 else
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +0000502 generator.emitPutSetterById(dst, *node->name(), Accessor, value);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000503 continue;
504 }
505
506 // This is a get/set property pair.
oliver@apple.com72d38322013-10-21 19:23:24 +0000507 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000508 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000509 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000510
511 // Was this already generated as a part of its partner?
512 if (pair.second == node)
513 continue;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000514
barraclough@apple.com09a55682012-01-30 18:28:39 +0000515 // Generate the paired node now.
516 RefPtr<RegisterID> getterReg;
517 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000518 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000519
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000520 if (node->m_type & PropertyNode::Getter) {
barraclough@apple.com09a55682012-01-30 18:28:39 +0000521 getterReg = value;
522 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000523 ASSERT(pair.second->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000524 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000525 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000526 } else {
527 setterReg = generator.newTemporary();
528 generator.emitLoad(setterReg.get(), jsUndefined());
529 }
530 } else {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000531 ASSERT(node->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000532 setterReg = value;
533 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000534 ASSERT(pair.second->m_type & PropertyNode::Getter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000535 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000536 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000537 } else {
538 getterReg = generator.newTemporary();
539 generator.emitLoad(getterReg.get(), jsUndefined());
540 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000541 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000542
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000543 ASSERT(!pair.second || isClassProperty == pair.second->needsSuperBinding());
544 if (isClassProperty && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000545 emitPutHomeObject(generator, secondReg, dst);
546
rniwa@webkit.org87ae29c2015-08-14 23:50:25 +0000547 generator.emitPutGetterSetter(dst, *node->name(), isClassProperty ? (Accessor | DontEnum) : Accessor, getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000548 }
549 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000550
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000551 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000552}
553
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000554void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
555{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000556 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000557 if (node.needsSuperBinding()) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000558 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000559
560 RefPtr<RegisterID> propertyNameRegister;
561 if (node.name())
562 propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node.name());
563 else
564 propertyNameRegister = generator.emitNode(node.m_expression);
565
566 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(),
567 value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
568 return;
569 }
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000570 if (const auto* identifier = node.name()) {
571 Optional<uint32_t> optionalIndex = parseIndex(*identifier);
572 if (!optionalIndex) {
573 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
574 return;
575 }
576
577 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
578 generator.emitDirectPutByVal(newObj, index.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000579 return;
580 }
581 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000582 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000583}
584
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000585// ------------------------------ BracketAccessorNode --------------------------------
586
587RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
588{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000589 if (m_base->isSuperNode()) {
590 // FIXME: Should we generate the profiler info?
591 if (m_subscript->isString()) {
592 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
593 return generator.emitGetById(generator.finalDestination(dst), emitSuperBaseForCallee(generator), id);
594 }
595 return generator.emitGetByVal(generator.finalDestination(dst), emitSuperBaseForCallee(generator), generator.emitNode(m_subscript));
596 }
597
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000598 RegisterID* ret;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000599 RegisterID* finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000600
601 if (m_subscript->isString()) {
602 RefPtr<RegisterID> base = generator.emitNode(m_base);
603 ret = generator.emitGetById(finalDest, base.get(), static_cast<StringNode*>(m_subscript)->value());
604 } else {
605 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
606 RegisterID* property = generator.emitNode(m_subscript);
607 ret = generator.emitGetByVal(finalDest, base.get(), property);
608 }
609
610 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
611
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000612 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000613 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000614}
615
616// ------------------------------ DotAccessorNode --------------------------------
617
618RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
619{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000620 RefPtr<RegisterID> base = m_base->isSuperNode() ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000621 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000622 RegisterID* finalDest = generator.finalDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000623 RegisterID* ret = generator.emitGetById(finalDest, base.get(), m_ident);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000624 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000625 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000626}
627
628// ------------------------------ ArgumentListNode -----------------------------
629
630RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
631{
632 ASSERT(m_expr);
633 return generator.emitNode(dst, m_expr);
634}
635
636// ------------------------------ NewExprNode ----------------------------------
637
638RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
639{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000640 ExpectedFunction expectedFunction;
641 if (m_expr->isResolveNode())
642 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
643 else
644 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000645 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000646 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000647 CallArguments callArguments(generator, m_args);
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000648 generator.emitMove(callArguments.thisRegister(), func.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000649 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000650}
651
oliver@apple.com72f8a822013-10-17 01:02:34 +0000652CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000653 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000654 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000655{
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +0000656 if (generator.shouldEmitProfileHooks())
657 m_profileHookRegister = generator.newTemporary();
ggaren@apple.com50c5ac22011-11-14 23:16:27 +0000658
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000659 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000660 if (argumentsNode) {
661 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
662 ++argumentCountIncludingThis;
663 }
664
665 m_argv.grow(argumentCountIncludingThis);
666 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
667 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000668 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 +0000669 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000670
671 while (stackOffset() % stackAlignmentRegisters()) {
672 m_argv.insert(0, generator.newTemporary());
673 m_padding++;
674 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000675}
676
677// ------------------------------ EvalFunctionCallNode ----------------------------------
678
679RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
680{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000681 Variable var = generator.variable(generator.propertyNames().eval);
682 if (RegisterID* local = var.local()) {
683 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000684 CallArguments callArguments(generator, m_args);
685 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000686 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000687 }
688
689 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000690 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000691 JSTextPosition newDivot = divotStart() + 4;
692 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000693 generator.moveToDestinationIfNeeded(
694 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000695 generator.emitResolveScope(callArguments.thisRegister(), var));
696 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000697 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000698}
699
700// ------------------------------ FunctionCallValueNode ----------------------------------
701
702RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
703{
704 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000705 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000706 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000707 if (m_expr->isSuperNode()) {
rniwa@webkit.orge6f83492015-03-13 23:01:51 +0000708 ASSERT(generator.isConstructor());
709 ASSERT(generator.constructorKind() == ConstructorKind::Derived);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000710 generator.emitMove(callArguments.thisRegister(), generator.newTarget());
711 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
712 generator.emitMove(generator.thisRegister(), ret);
713 return ret;
714 }
oliver@apple.com64126552010-10-18 18:32:39 +0000715 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000716 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000717 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000718 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000719}
720
721// ------------------------------ FunctionCallResolveNode ----------------------------------
722
723RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
724{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000725 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000726
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000727 Variable var = generator.variable(m_ident);
728 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000729 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000730 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000731 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000732 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000733 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000734 // This passes NoExpectedFunction because we expect that if the function is in a
735 // local variable, then it's not one of our built-in constructors.
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000736 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000737 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000738 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000739 }
740
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000741 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000742 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000743 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000744
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000745 JSTextPosition newDivot = divotStart() + m_ident.length();
746 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000747 generator.moveToDestinationIfNeeded(
748 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000749 generator.emitResolveScope(callArguments.thisRegister(), var));
750 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000751 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000752 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000753 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000754 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000755}
756
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000757// ------------------------------ BytecodeIntrinsicNode ----------------------------------
758
759RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
760{
761 return (this->*m_emitter)(generator, dst);
762}
763
764RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
765{
766 ArgumentListNode* node = m_args->m_listNode;
767 RefPtr<RegisterID> base = generator.emitNode(node);
768 node = node->m_next;
769 RefPtr<RegisterID> index = generator.emitNode(node);
770 node = node->m_next;
771 RefPtr<RegisterID> value = generator.emitNode(node);
772
773 ASSERT(!node->m_next);
774
775 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
776}
777
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +0000778RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
779{
780 ArgumentListNode* node = m_args->m_listNode;
781 RefPtr<RegisterID> src = generator.emitNode(node);
782 ASSERT(!node->m_next);
783
784 return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
785}
786
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000787// ------------------------------ FunctionCallBracketNode ----------------------------------
788
789RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
790{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000791 bool baseIsSuper = m_base->isSuperNode();
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +0000792 bool subscriptIsString = m_subscript->isString();
793
794 RefPtr<RegisterID> base;
795 if (baseIsSuper)
796 base = emitSuperBaseForCallee(generator);
797 else {
798 if (subscriptIsString)
799 base = generator.emitNode(m_base);
800 else
801 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
802 }
803
804 RefPtr<RegisterID> function;
805 if (subscriptIsString) {
806 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
807 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
808 } else {
809 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
810 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
811 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
812 }
813
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000814 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000815 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000816 if (baseIsSuper)
817 generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
818 else
819 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000820 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000821 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000822 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000823}
824
825// ------------------------------ FunctionCallDotNode ----------------------------------
826
827RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
828{
829 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000830 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000831 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000832 bool baseIsSuper = m_base->isSuperNode();
833 if (baseIsSuper)
834 generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
835 else
836 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000837 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000838 generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000839 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000840 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000841 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000842}
843
844RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
845{
846 RefPtr<Label> realCall = generator.newLabel();
847 RefPtr<Label> end = generator.newLabel();
848 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000849 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000850 RefPtr<RegisterID> function;
oliver@apple.comba848d12014-02-12 17:14:23 +0000851 bool emitCallCheck = !generator.isBuiltinFunction();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000852 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000853 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000854 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000855 }
856 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000857 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000858 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
859 RefPtr<RegisterID> profileHookRegister;
860 if (generator.shouldEmitProfileHooks())
861 profileHookRegister = generator.newTemporary();
862 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
863 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000864 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000865 argumentsRegister = generator.emitNode(subject);
866 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
867 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000868 generator.emitCallVarargsInTailPosition(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000869 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000870 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000871 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +0000872
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000873 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
874 CallArguments callArguments(generator, m_args);
875 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000876 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000877 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000878 } else {
879 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
880 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000881 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000882 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000883 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000884 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000885 if (emitCallCheck) {
886 generator.emitJump(end.get());
887 generator.emitLabel(realCall.get());
888 {
889 CallArguments callArguments(generator, m_args);
890 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000891 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000892 }
893 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000894 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000895 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000896 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000897}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000898
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000899static bool areTrivialApplyArguments(ArgumentsNode* args)
900{
901 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
902 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
903}
904
905RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
906{
907 // A few simple cases can be trivially handled as ordinary function calls.
908 // function.apply(), function.apply(arg) -> identical to function.call
909 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
910 bool mayBeCall = areTrivialApplyArguments(m_args);
911
912 RefPtr<Label> realCall = generator.newLabel();
913 RefPtr<Label> end = generator.newLabel();
914 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000915 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000916 RefPtr<RegisterID> function;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000917 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000918 bool emitCallCheck = !generator.isBuiltinFunction();
919 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000920 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000921 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
922 }
923 if (mayBeCall) {
924 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
925 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +0000926 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
927 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
928 RefPtr<RegisterID> profileHookRegister;
929 if (generator.shouldEmitProfileHooks())
930 profileHookRegister = generator.newTemporary();
931 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
932 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
933 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
934 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
935
936 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
937 {
938 RefPtr<Label> haveThis = generator.newLabel();
939 RefPtr<Label> end = generator.newLabel();
940 RefPtr<RegisterID> compareResult = generator.newTemporary();
941 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
942 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
943 generator.emitMove(thisRegister.get(), value);
944 generator.emitLoad(index.get(), jsNumber(1));
945 generator.emitJump(end.get());
946 generator.emitLabel(haveThis.get());
947 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
948 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
949 generator.emitMove(argumentsRegister.get(), value);
950 generator.emitLoad(index.get(), jsNumber(2));
951 generator.emitLabel(end.get());
952 };
953 generator.emitEnumeration(this, spread->expression(), extractor);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000954 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
oliver@apple.com0989d9b2014-02-26 20:40:46 +0000955 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +0000956 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
957 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000958 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 +0000959 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
960 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +0000961 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000962 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000963 } else {
964 m_args->m_listNode = m_args->m_listNode->m_next;
965 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
966 CallArguments callArguments(generator, m_args);
967 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000968 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000969 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000970 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000971 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +0000972 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000973 CallArguments callArguments(generator, m_args);
974 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000975 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000976 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000977 } else {
978 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
979 RefPtr<RegisterID> profileHookRegister;
980 if (generator.shouldEmitProfileHooks())
981 profileHookRegister = generator.newTemporary();
982 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
983 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
984 RefPtr<RegisterID> argsRegister;
985 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000986 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +0000987
988 // Function.prototype.apply ignores extra arguments, but we still
989 // need to evaluate them for side effects.
990 while ((args = args->m_next))
991 generator.emitNode(args->m_expr);
992
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000993 generator.emitCallVarargsInTailPosition(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
oliver@apple.comd04e0a02014-02-01 01:37:59 +0000994 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000995 if (emitCallCheck) {
996 generator.emitJump(end.get());
997 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000998 CallArguments callArguments(generator, m_args);
999 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001000 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001001 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001002 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001003 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001004 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001005}
1006
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001007// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001008
ggaren@apple.comf3036112013-04-27 23:14:04 +00001009static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001010{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001011 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001012}
1013
1014static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1015{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001016 if (dst == srcDst)
1017 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1018 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1019 emitIncOrDec(generator, srcDst, oper);
1020 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001021}
1022
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001023RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001024{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001025 if (dst == generator.ignoredResult())
1026 return PrefixNode::emitResolve(generator, dst);
1027
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001028 ASSERT(m_expr->isResolveNode());
1029 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1030 const Identifier& ident = resolve->identifier();
1031
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001032 Variable var = generator.variable(ident);
1033 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001034 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001035 RefPtr<RegisterID> localReg = local;
1036 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001037 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001038 localReg = generator.emitMove(generator.tempDestination(dst), local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001039 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001040 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1041 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1042 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001043 }
oliver@apple.com75f804e2013-03-07 00:25:20 +00001044
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001045 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001046 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1047 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001048 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001049 if (var.isReadOnly()) {
1050 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1051 if (threwException)
1052 return value.get();
1053 }
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001054 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001055 if (!var.isReadOnly()) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001056 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001057 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1058 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001059
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001060 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001061}
1062
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001063RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001064{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001065 if (dst == generator.ignoredResult())
1066 return PrefixNode::emitBracket(generator, dst);
1067
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001068 ASSERT(m_expr->isBracketAccessorNode());
1069 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1070 ExpressionNode* baseNode = bracketAccessor->base();
1071 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001072
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001073 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001074 RefPtr<RegisterID> property = generator.emitNode(subscript);
1075
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001076 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001077 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001078 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001079 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001080 generator.emitPutByVal(base.get(), property.get(), value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001081 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001082 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001083}
1084
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001085RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001086{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001087 if (dst == generator.ignoredResult())
1088 return PrefixNode::emitDot(generator, dst);
1089
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001090 ASSERT(m_expr->isDotAccessorNode());
1091 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1092 ExpressionNode* baseNode = dotAccessor->base();
1093 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001094
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001095 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1096
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001097 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001098 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001099 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001100 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001101 generator.emitPutById(base.get(), ident, value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001102 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001103 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001104}
1105
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001106RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001107{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001108 if (m_expr->isResolveNode())
1109 return emitResolve(generator, dst);
1110
1111 if (m_expr->isBracketAccessorNode())
1112 return emitBracket(generator, dst);
1113
1114 if (m_expr->isDotAccessorNode())
1115 return emitDot(generator, dst);
1116
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001117 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001118 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1119 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001120}
1121
1122// ------------------------------ DeleteResolveNode -----------------------------------
1123
1124RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1125{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001126 Variable var = generator.variable(m_ident);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001127 if (var.local()) {
1128 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001129 return generator.emitLoad(generator.finalDestination(dst), false);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001130 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001131
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001132 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001133 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001134 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
oliver@apple.com58c86752013-07-25 04:02:40 +00001135 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001136}
1137
1138// ------------------------------ DeleteBracketNode -----------------------------------
1139
1140RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1141{
1142 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001143 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001144
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001145 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001146 if (m_base->isSuperNode())
1147 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001148 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001149}
1150
1151// ------------------------------ DeleteDotNode -----------------------------------
1152
1153RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1154{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001155 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001156
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001157 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001158 if (m_base->isSuperNode())
1159 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001160 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001161}
1162
1163// ------------------------------ DeleteValueNode -----------------------------------
1164
1165RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1166{
1167 generator.emitNode(generator.ignoredResult(), m_expr);
1168
1169 // delete on a non-location expression ignores the value and returns true
1170 return generator.emitLoad(generator.finalDestination(dst), true);
1171}
1172
1173// ------------------------------ VoidNode -------------------------------------
1174
1175RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1176{
1177 if (dst == generator.ignoredResult()) {
1178 generator.emitNode(generator.ignoredResult(), m_expr);
1179 return 0;
1180 }
1181 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1182 return generator.emitLoad(dst, jsUndefined());
1183}
1184
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001185// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001186
1187RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1188{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001189 Variable var = generator.variable(m_ident);
1190 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001191 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001192 if (dst == generator.ignoredResult())
1193 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001194 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001195 }
1196
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001197 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1198 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001199 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001200 if (dst == generator.ignoredResult())
1201 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001202 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001203}
1204
1205// ------------------------------ TypeOfValueNode -----------------------------------
1206
1207RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1208{
1209 if (dst == generator.ignoredResult()) {
1210 generator.emitNode(generator.ignoredResult(), m_expr);
1211 return 0;
1212 }
1213 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1214 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1215}
1216
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001217// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001218
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001219RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001220{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001221 ASSERT(m_expr->isResolveNode());
1222 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1223 const Identifier& ident = resolve->identifier();
1224
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001225 Variable var = generator.variable(ident);
1226 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001227 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001228 RefPtr<RegisterID> localReg = local;
1229 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001230 generator.emitReadOnlyExceptionIfNeeded(var);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001231 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001232 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001233 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001234 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001235 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001236 generator.emitMove(localReg.get(), tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001237 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001238 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1239 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001240 emitIncOrDec(generator, localReg.get(), m_operator);
1241 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001242 }
1243
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001244 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001245 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1246 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001247 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001248 if (var.isReadOnly()) {
1249 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1250 if (threwException)
1251 return value.get();
1252 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001253
oliver@apple.com58c86752013-07-25 04:02:40 +00001254 emitIncOrDec(generator, value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001255 if (!var.isReadOnly()) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001256 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001257 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1258 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001259 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001260}
1261
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001262RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001263{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001264 ASSERT(m_expr->isBracketAccessorNode());
1265 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1266 ExpressionNode* baseNode = bracketAccessor->base();
1267 ExpressionNode* subscript = bracketAccessor->subscript();
1268
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001269 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001270 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001271 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1272
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001273 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001274 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001275 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001276 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001277 generator.emitPutByVal(base.get(), property.get(), value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001278 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001279 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1280}
1281
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001282RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001283{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001284 ASSERT(m_expr->isDotAccessorNode());
1285 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1286 ExpressionNode* baseNode = dotAccessor->base();
1287 const Identifier& ident = dotAccessor->identifier();
1288
1289 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001290 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1291
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001292 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001293 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001294 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001295 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001296 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001297 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001298 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1299}
1300
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001301RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001302{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001303 if (m_expr->isResolveNode())
1304 return emitResolve(generator, dst);
1305
1306 if (m_expr->isBracketAccessorNode())
1307 return emitBracket(generator, dst);
1308
1309 if (m_expr->isDotAccessorNode())
1310 return emitDot(generator, dst);
1311
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001312 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001313 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1314 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001315}
1316
1317// ------------------------------ Unary Operation Nodes -----------------------------------
1318
1319RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1320{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001321 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001322 generator.emitExpressionInfo(position(), position(), position());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001323 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001324}
1325
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001326// ------------------------------ BitwiseNotNode -----------------------------------
1327
1328RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1329{
1330 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001331 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1332 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 +00001333}
1334
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001335// ------------------------------ LogicalNotNode -----------------------------------
1336
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001337void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001338{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001339 // reverse the true and false targets
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001340 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001341}
1342
1343
1344// ------------------------------ Binary Operation Nodes -----------------------------------
1345
1346// BinaryOpNode::emitStrcat:
1347//
1348// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1349// more values, where we can determine a set of separate op_add operations would be operating on
1350// string values.
1351//
1352// This function expects to be operating on a graph of AST nodes looking something like this:
1353//
1354// (a)... (b)
1355// \ /
1356// (+) (c)
1357// \ /
1358// [d] ((+))
1359// \ /
1360// [+=]
1361//
1362// The assignment operation is optional, if it exists the register holding the value on the
1363// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1364//
1365// The method should be called on the node at the root of the tree of regular binary add
1366// operations (marked in the diagram with a double set of parentheses). This node must
1367// be performing a string concatenation (determined by statically detecting that at least
1368// one child must be a string).
1369//
1370// Since the minimum number of values being concatenated together is expected to be 3, if
1371// a lhs to a concatenating assignment is not provided then the root add should have at
1372// least one left child that is also an add that can be determined to be operating on strings.
1373//
1374RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1375{
1376 ASSERT(isAdd());
1377 ASSERT(resultDescriptor().definitelyIsString());
1378
1379 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1380 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1381 // added first, and the leftmost child is never added, so the vector produced for the
1382 // example above will be [ c, b ].
1383 Vector<ExpressionNode*, 16> reverseExpressionList;
1384 reverseExpressionList.append(m_expr2);
1385
1386 // Examine the left child of the add. So long as this is a string add, add its right-child
1387 // to the list, and keep processing along the left fork.
1388 ExpressionNode* leftMostAddChild = m_expr1;
1389 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1390 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1391 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1392 }
1393
1394 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1395
1396 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1397 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1398 // op_strcat node handle its conversion if required).
1399 if (lhs)
1400 temporaryRegisters.append(generator.newTemporary());
1401
1402 // Emit code for the leftmost node ((a) in the example).
1403 temporaryRegisters.append(generator.newTemporary());
1404 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1405 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1406
1407 // Note on ordering of conversions:
1408 //
1409 // We maintain the same ordering of conversions as we would see if the concatenations
1410 // was performed as a sequence of adds (otherwise this optimization could change
1411 // behaviour should an object have been provided a valueOf or toString method).
1412 //
1413 // Considering the above example, the sequnce of execution is:
1414 // * evaluate operand (a)
1415 // * evaluate operand (b)
1416 // * convert (a) to primitive <- (this would be triggered by the first add)
1417 // * convert (b) to primitive <- (ditto)
1418 // * evaluate operand (c)
1419 // * convert (c) to primitive <- (this would be triggered by the second add)
1420 // And optionally, if there is an assignment:
1421 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1422 //
1423 // As such we do not plant an op to convert the leftmost child now. Instead, use
1424 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1425 // once the second node has been generated. However, if the leftmost child is an
1426 // immediate we can trivially determine that no conversion will be required.
1427 // If this is the case
1428 if (leftMostAddChild->isString())
1429 leftMostAddChildTempRegister = 0;
1430
1431 while (reverseExpressionList.size()) {
1432 ExpressionNode* node = reverseExpressionList.last();
1433 reverseExpressionList.removeLast();
1434
1435 // Emit the code for the current node.
1436 temporaryRegisters.append(generator.newTemporary());
1437 generator.emitNode(temporaryRegisters.last().get(), node);
1438
1439 // On the first iteration of this loop, when we first reach this point we have just
1440 // generated the second node, which means it is time to convert the leftmost operand.
1441 if (leftMostAddChildTempRegister) {
1442 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1443 leftMostAddChildTempRegister = 0; // Only do this once.
1444 }
1445 // Plant a conversion for this node, if necessary.
1446 if (!node->isString())
1447 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1448 }
1449 ASSERT(temporaryRegisters.size() >= 3);
1450
1451 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1452 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1453 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001454 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001455 // If there is an assignment convert the lhs now. This will also copy lhs to
1456 // the temporary register we allocated for it.
1457 if (lhs)
1458 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1459
1460 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1461}
1462
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001463void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1464{
1465 TriState branchCondition;
1466 ExpressionNode* branchExpression;
1467 tryFoldToBranch(generator, branchCondition, branchExpression);
1468
1469 if (branchCondition == MixedTriState)
1470 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1471 else if (branchCondition == TrueTriState)
1472 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1473 else
1474 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1475}
1476
1477static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1478{
1479 ResultType expressionType = branchExpression->resultDescriptor();
1480
1481 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1482 return true;
1483 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1484 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1485 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1486 return true;
1487
1488 return false;
1489}
1490
1491void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1492{
1493 branchCondition = MixedTriState;
1494 branchExpression = 0;
1495
1496 ConstantNode* constant = 0;
1497 if (m_expr1->isConstant()) {
1498 constant = static_cast<ConstantNode*>(m_expr1);
1499 branchExpression = m_expr2;
1500 } else if (m_expr2->isConstant()) {
1501 constant = static_cast<ConstantNode*>(m_expr2);
1502 branchExpression = m_expr1;
1503 }
1504
1505 if (!constant)
1506 return;
1507 ASSERT(branchExpression);
1508
1509 OpcodeID opcodeID = this->opcodeID();
1510 JSValue value = constant->jsValue(generator);
1511 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1512 if (!canFoldToBranch)
1513 return;
1514
1515 if (opcodeID == op_eq || opcodeID == op_stricteq)
1516 branchCondition = triState(value.pureToBoolean());
1517 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1518 branchCondition = triState(!value.pureToBoolean());
1519}
1520
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001521RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1522{
1523 OpcodeID opcodeID = this->opcodeID();
1524
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001525 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001526 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001527 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001528 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001529
1530 if (opcodeID == op_neq) {
1531 if (m_expr1->isNull() || m_expr2->isNull()) {
1532 RefPtr<RegisterID> src = generator.tempDestination(dst);
1533 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1534 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1535 }
1536 }
1537
oliver@apple.comece74042012-12-01 00:50:39 +00001538 ExpressionNode* left = m_expr1;
1539 ExpressionNode* right = m_expr2;
1540 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1541 if (left->isString())
1542 std::swap(left, right);
1543 }
1544
1545 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001546 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001547 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001548 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001549 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001550 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1551 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001552 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001553 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001554 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001555 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001556 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001557 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1558 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001559 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 +00001560 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1561 return generator.emitUnaryOp(op_unsigned, result, result);
1562 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001563}
1564
1565RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1566{
1567 if (m_expr1->isNull() || m_expr2->isNull()) {
1568 RefPtr<RegisterID> src = generator.tempDestination(dst);
1569 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1570 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1571 }
1572
oliver@apple.comece74042012-12-01 00:50:39 +00001573 ExpressionNode* left = m_expr1;
1574 ExpressionNode* right = m_expr2;
1575 if (left->isString())
1576 std::swap(left, right);
1577
1578 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001579 RefPtr<RegisterID> src2 = generator.emitNode(right);
1580 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001581}
1582
1583RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1584{
oliver@apple.comece74042012-12-01 00:50:39 +00001585 ExpressionNode* left = m_expr1;
1586 ExpressionNode* right = m_expr2;
1587 if (left->isString())
1588 std::swap(left, right);
1589
1590 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001591 RefPtr<RegisterID> src2 = generator.emitNode(right);
1592 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001593}
1594
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001595RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1596{
1597 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001598 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001599 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001600 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 +00001601}
1602
1603RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1604{
1605 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1606 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001607 RefPtr<RegisterID> prototype = generator.newTemporary();
1608 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1609 RefPtr<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001610
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001611 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001612 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001613
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001614 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00001615 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001616
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001617 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com094dbd92012-09-22 01:18:54 +00001618 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001619 generator.emitLabel(target.get());
1620 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001621}
1622
1623// ------------------------------ LogicalOpNode ----------------------------
1624
1625RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1626{
1627 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1628 RefPtr<Label> target = generator.newLabel();
1629
1630 generator.emitNode(temp.get(), m_expr1);
1631 if (m_operator == OpLogicalAnd)
1632 generator.emitJumpIfFalse(temp.get(), target.get());
1633 else
1634 generator.emitJumpIfTrue(temp.get(), target.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001635 generator.emitNodeInTailPosition(temp.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001636 generator.emitLabel(target.get());
1637
1638 return generator.moveToDestinationIfNeeded(dst, temp.get());
1639}
1640
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001641void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001642{
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001643 RefPtr<Label> afterExpr1 = generator.newLabel();
1644 if (m_operator == OpLogicalAnd)
1645 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1646 else
1647 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1648 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001649
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001650 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001651}
1652
1653// ------------------------------ ConditionalNode ------------------------------
1654
1655RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1656{
1657 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1658 RefPtr<Label> beforeElse = generator.newLabel();
1659 RefPtr<Label> afterElse = generator.newLabel();
1660
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001661 RefPtr<Label> beforeThen = generator.newLabel();
1662 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1663 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001664
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001665 generator.emitProfileControlFlow(m_expr1->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001666 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001667 generator.emitJump(afterElse.get());
1668
1669 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001670 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001671 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001672
1673 generator.emitLabel(afterElse.get());
1674
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001675 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001676
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001677 return newDst.get();
1678}
1679
1680// ------------------------------ ReadModifyResolveNode -----------------------------------
1681
1682// FIXME: should this be moved to be a method on BytecodeGenerator?
1683static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1684{
1685 OpcodeID opcodeID;
1686 switch (oper) {
1687 case OpMultEq:
1688 opcodeID = op_mul;
1689 break;
1690 case OpDivEq:
1691 opcodeID = op_div;
1692 break;
1693 case OpPlusEq:
1694 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1695 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1696 opcodeID = op_add;
1697 break;
1698 case OpMinusEq:
1699 opcodeID = op_sub;
1700 break;
1701 case OpLShift:
1702 opcodeID = op_lshift;
1703 break;
1704 case OpRShift:
1705 opcodeID = op_rshift;
1706 break;
1707 case OpURShift:
1708 opcodeID = op_urshift;
1709 break;
1710 case OpAndEq:
1711 opcodeID = op_bitand;
1712 break;
1713 case OpXOrEq:
1714 opcodeID = op_bitxor;
1715 break;
1716 case OpOrEq:
1717 opcodeID = op_bitor;
1718 break;
1719 case OpModEq:
1720 opcodeID = op_mod;
1721 break;
1722 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001723 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001724 return dst;
1725 }
1726
1727 RegisterID* src2 = generator.emitNode(m_right);
1728
1729 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1730 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1731 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001732 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001733 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1734 if (oper == OpURShift)
1735 return generator.emitUnaryOp(op_unsigned, result, result);
1736 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001737}
1738
1739RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1740{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00001741 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001742 Variable var = generator.variable(m_ident);
1743 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001744 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001745 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001746 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001747 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1748 generator.emitProfileType(result, divotStart(), divotEnd());
1749 return result;
ggaren@apple.com6e309822012-09-05 21:44:43 +00001750 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001751
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001752 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001753 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001754 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001755 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001756 generator.emitMove(local, result.get());
1757 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001758 generator.emitProfileType(local, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001759 return generator.moveToDestinationIfNeeded(dst, result.get());
1760 }
1761
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001762 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1763 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001764 generator.emitProfileType(result, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001765 return generator.moveToDestinationIfNeeded(dst, result);
1766 }
1767
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001768 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001769 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1770 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001771 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001772 if (var.isReadOnly()) {
1773 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1774 if (threwException)
1775 return value.get();
1776 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001777 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 +00001778 RegisterID* returnResult = result.get();
1779 if (!var.isReadOnly()) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001780 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001781 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
1782 }
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001783 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001784}
1785
1786// ------------------------------ AssignResolveNode -----------------------------------
1787
1788RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1789{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001790 Variable var = generator.variable(m_ident);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001791 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001792 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001793 RegisterID* result = nullptr;
1794 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
1795 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001796
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001797 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00001798 result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001799 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001800 generator.emitProfileType(result, var, divotStart(), divotEnd());
1801 } else if (var.isSpecial()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001802 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1803 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001804 generator.emitMove(local, tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001805 generator.emitProfileType(local, var, divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001806 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001807 result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
1808 } else {
1809 RegisterID* right = generator.emitNode(local, m_right);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001810 generator.emitProfileType(right, var, divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001811 generator.invalidateForInContextForLocal(local);
1812 result = generator.moveToDestinationIfNeeded(dst, right);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001813 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001814
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001815 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001816 generator.liftTDZCheckIfPossible(var);
1817 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001818 }
1819
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001820 if (generator.isStrictMode())
1821 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001822 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001823 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
1824 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001825 if (dst == generator.ignoredResult())
1826 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001827 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001828 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00001829 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001830 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1831 if (threwException)
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00001832 return result;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001833 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001834 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001835 RegisterID* returnResult = result.get();
1836 if (!isReadOnly) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001837 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound,
1838 m_assignmentContext == AssignmentContext::ConstDeclarationStatement || m_assignmentContext == AssignmentContext::DeclarationStatement ? Initialization : NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001839 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
1840 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001841
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001842 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001843 generator.liftTDZCheckIfPossible(var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001844 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001845}
1846
1847// ------------------------------ AssignDotNode -----------------------------------
1848
1849RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1850{
1851 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1852 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001853 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001854 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001855 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001856 generator.emitPutById(base.get(), m_ident, forwardResult);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001857 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001858 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001859}
1860
1861// ------------------------------ ReadModifyDotNode -----------------------------------
1862
1863RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1864{
1865 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1866
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001867 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001868 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001869 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 +00001870
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001871 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001872 RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001873 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001874 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001875}
1876
1877// ------------------------------ AssignErrorNode -----------------------------------
1878
1879RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1880{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001881 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001882}
1883
1884// ------------------------------ AssignBracketNode -----------------------------------
1885
1886RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1887{
1888 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1889 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1890 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001891 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001892
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001893 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001894 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00001895
1896 if (m_subscript->isString())
1897 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
1898 else
1899 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1900
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001901 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001902 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001903}
1904
1905// ------------------------------ ReadModifyBracketNode -----------------------------------
1906
1907RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1908{
1909 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1910 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1911
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001912 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001913 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001914 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 +00001915
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001916 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001917 generator.emitPutByVal(base.get(), property.get(), updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001918 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001919
1920 return updatedValue;
1921}
1922
1923// ------------------------------ CommaNode ------------------------------------
1924
1925RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1926{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001927 CommaNode* node = this;
1928 for (; node && node->next(); node = node->next())
1929 generator.emitNode(generator.ignoredResult(), node->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001930 return generator.emitNodeInTailPosition(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001931}
1932
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001933// ------------------------------ SourceElements -------------------------------
1934
1935
1936inline StatementNode* SourceElements::lastStatement() const
1937{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001938 return m_tail;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001939}
1940
1941inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1942{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001943 for (StatementNode* statement = m_head; statement; statement = statement->next())
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001944 generator.emitNodeInTailPosition(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001945}
1946
1947// ------------------------------ BlockNode ------------------------------------
1948
1949inline StatementNode* BlockNode::lastStatement() const
1950{
1951 return m_statements ? m_statements->lastStatement() : 0;
1952}
1953
ggaren@apple.comddc6f102015-03-20 20:12:10 +00001954StatementNode* BlockNode::singleStatement() const
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00001955{
1956 return m_statements ? m_statements->singleStatement() : 0;
1957}
1958
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001959void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001960{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001961 if (!m_statements)
1962 return;
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001963 generator.pushLexicalScope(this, true);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001964 m_statements->emitBytecode(generator, dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001965 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001966}
1967
1968// ------------------------------ EmptyStatementNode ---------------------------
1969
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001970void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001971{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001972 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001973}
1974
1975// ------------------------------ DebuggerStatementNode ---------------------------
1976
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001977void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001978{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001979 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001980}
1981
1982// ------------------------------ ExprStatementNode ----------------------------
1983
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001984void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001985{
1986 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001987 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001988 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001989}
1990
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001991// ------------------------------ DeclarationStatement ----------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001992
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001993void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001994{
1995 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001996 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001997 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001998}
1999
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002000// ------------------------------ EmptyVarExpression ----------------------------
2001
2002RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2003{
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002004 // 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 +00002005 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002006 return nullptr;
2007
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002008 Variable var = generator.variable(m_ident);
2009 if (RegisterID* local = var.local())
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002010 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002011 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002012 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2013 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002014 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002015 }
2016
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002017 return nullptr;
2018}
2019
2020// ------------------------------ EmptyLetExpression ----------------------------
2021
2022RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2023{
2024 // Lexical declarations like 'let' must move undefined into their variables so we don't
2025 // get TDZ errors for situations like this: `let x; x;`
2026 Variable var = generator.variable(m_ident);
2027 if (RegisterID* local = var.local()) {
2028 generator.emitLoad(local, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002029 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002030 } else {
2031 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2032 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002033 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, Initialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002034 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002035 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002036
2037 // 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 +00002038 return nullptr;
2039}
2040
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002041// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002042
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002043static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002044{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002045 if (statementNode->isBlock())
2046 return static_cast<BlockNode*>(statementNode)->singleStatement();
2047 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002048}
2049
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002050bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2051 Label*& trueTarget, FallThroughMode& fallThroughMode)
2052{
2053 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2054 if (!singleStatement)
2055 return false;
2056
2057 if (singleStatement->isBreak()) {
2058 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2059 Label* target = breakNode->trivialTarget(generator);
2060 if (!target)
2061 return false;
2062 trueTarget = target;
2063 fallThroughMode = FallThroughMeansFalse;
2064 return true;
2065 }
2066
2067 if (singleStatement->isContinue()) {
2068 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2069 Label* target = continueNode->trivialTarget(generator);
2070 if (!target)
2071 return false;
2072 trueTarget = target;
2073 fallThroughMode = FallThroughMeansFalse;
2074 return true;
2075 }
2076
2077 return false;
2078}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002079
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002080void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002081{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002082 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00002083
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002084 RefPtr<Label> beforeThen = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002085 RefPtr<Label> beforeElse = generator.newLabel();
2086 RefPtr<Label> afterElse = generator.newLabel();
2087
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002088 Label* trueTarget = beforeThen.get();
2089 Label* falseTarget = beforeElse.get();
2090 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2091 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2092
2093 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002094 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002095 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002096
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002097 if (!didFoldIfBlock) {
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002098 generator.emitNodeInTailPosition(dst, m_ifBlock);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002099 if (m_elseBlock)
2100 generator.emitJump(afterElse.get());
2101 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002102
2103 generator.emitLabel(beforeElse.get());
2104
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002105 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002106 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002107 generator.emitNodeInTailPosition(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002108 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002109
2110 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002111 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2112 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002113}
2114
2115// ------------------------------ DoWhileNode ----------------------------------
2116
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002117void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002118{
oliver@apple.com6a976452013-03-11 21:02:39 +00002119 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002120
2121 RefPtr<Label> topOfLoop = generator.newLabel();
2122 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002123 generator.emitLoopHint();
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002124 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002125
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002126 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002127
2128 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002129 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002130 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002131
2132 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002133}
2134
2135// ------------------------------ WhileNode ------------------------------------
2136
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002137void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002138{
oliver@apple.com6a976452013-03-11 21:02:39 +00002139 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002140 RefPtr<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002141
ggaren@apple.com8e8bac42015-03-26 23:35:47 +00002142 generator.emitDebugHook(WillExecuteStatement, m_expr->firstLine(), m_expr->startOffset(), m_expr->lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002143 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002144
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002145 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002146 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002147
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002148 generator.emitProfileControlFlow(m_statement->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002149 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002150
2151 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002152 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002153
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002154 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002155
2156 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002157
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002158 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002159}
2160
2161// ------------------------------ ForNode --------------------------------------
2162
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002163void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002164{
oliver@apple.com6a976452013-03-11 21:02:39 +00002165 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002166
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002167 RegisterID* forLoopSymbolTable = nullptr;
2168 generator.pushLexicalScope(this, true, &forLoopSymbolTable);
2169
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002170 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002171
2172 if (m_expr1)
2173 generator.emitNode(generator.ignoredResult(), m_expr1);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002174
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002175 RefPtr<Label> topOfLoop = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002176 if (m_expr2)
2177 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002178
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002179 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002180 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002181 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002182
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002183 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002184
2185 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002186 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002187 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002188 if (m_expr3)
2189 generator.emitNode(generator.ignoredResult(), m_expr3);
2190
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002191 if (m_expr2)
2192 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2193 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002194 generator.emitJump(topOfLoop.get());
2195
2196 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002197 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002198 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002199}
2200
2201// ------------------------------ ForInNode ------------------------------------
2202
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002203RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002204{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002205 if (m_lexpr->isResolveNode()) {
2206 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002207 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002208 }
2209
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002210 if (m_lexpr->isDestructuringNode()) {
2211 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002212 auto binding = assignNode->bindings();
2213 if (!binding->isBindingNode())
2214 return nullptr;
2215
2216 auto simpleBinding = static_cast<BindingNode*>(binding);
2217 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002218 Variable var = generator.variable(ident);
2219 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002220 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002221 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002222 }
2223
2224 return nullptr;
2225}
2226
2227void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2228{
2229 if (m_lexpr->isResolveNode()) {
2230 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002231 Variable var = generator.variable(ident);
2232 if (RegisterID* local = var.local())
2233 generator.emitMove(local, propertyName);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002234 else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002235 if (generator.isStrictMode())
2236 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002237 RegisterID* scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002238 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002239 generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002240 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002241 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002242 return;
2243 }
2244 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002245 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2246 const Identifier& ident = assignNode->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002247 RegisterID* base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002248 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002249 generator.emitPutById(base, ident, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002250 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002251 return;
2252 }
2253 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002254 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002255 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2256 RegisterID* subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002257 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002258 generator.emitPutByVal(base.get(), subscript, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002259 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002260 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002261 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002262
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002263 if (m_lexpr->isDestructuringNode()) {
2264 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002265 auto binding = assignNode->bindings();
2266 if (!binding->isBindingNode()) {
2267 assignNode->bindings()->bindValue(generator, propertyName);
2268 return;
2269 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002270
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002271 auto simpleBinding = static_cast<BindingNode*>(binding);
2272 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002273 Variable var = generator.variable(ident);
2274 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002275 assignNode->bindings()->bindValue(generator, propertyName);
2276 return;
2277 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002278 generator.emitMove(var.local(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002279 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002280 return;
2281 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002282
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002283 RELEASE_ASSERT_NOT_REACHED();
2284}
2285
2286void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
2287{
2288 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002289 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002290 return;
2291 }
2292
2293 RefPtr<Label> end = generator.newLabel();
2294
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002295 RegisterID* forLoopSymbolTable = nullptr;
2296 generator.pushLexicalScope(this, true, &forLoopSymbolTable);
2297
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002298 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002299
2300 RefPtr<RegisterID> base = generator.newTemporary();
2301 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002302 RefPtr<RegisterID> enumerator;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002303 generator.emitNode(base.get(), m_expr);
2304 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002305 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002306
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002307 int profilerStartOffset = m_statement->startOffset();
2308 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002309
2310 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2311
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002312 // Indexed property loop.
2313 {
2314 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2315 RefPtr<Label> loopStart = generator.newLabel();
2316 RefPtr<Label> loopEnd = generator.newLabel();
2317
msaboff@apple.comb644c252015-03-24 10:05:21 +00002318 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002319 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2320 RefPtr<RegisterID> propertyName = generator.newTemporary();
2321
2322 generator.emitLabel(loopStart.get());
2323 generator.emitLoopHint();
2324
2325 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2326 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2327 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
2328 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2329
2330 generator.emitToIndexString(propertyName.get(), i.get());
2331 this->emitLoopHeader(generator, propertyName.get());
2332
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002333 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002334
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002335 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002336 generator.emitNode(dst, m_statement);
2337 generator.popIndexedForInScope(local.get());
2338
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002339 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002340
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002341 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002342 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002343 generator.emitInc(i.get());
2344 generator.emitJump(loopStart.get());
2345
2346 generator.emitLabel(scope->breakTarget());
2347 generator.emitJump(end.get());
2348 generator.emitLabel(loopEnd.get());
2349 }
2350
2351 // Structure property loop.
2352 {
2353 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2354 RefPtr<Label> loopStart = generator.newLabel();
2355 RefPtr<Label> loopEnd = generator.newLabel();
2356
msaboff@apple.comb644c252015-03-24 10:05:21 +00002357 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002358 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002359 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002360
2361 generator.emitLabel(loopStart.get());
2362 generator.emitLoopHint();
2363
2364 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2365 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002366 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002367 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2368
2369 this->emitLoopHeader(generator, propertyName.get());
2370
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002371 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002372
msaboff@apple.comb644c252015-03-24 10:05:21 +00002373 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002374 generator.emitNode(dst, m_statement);
2375 generator.popStructureForInScope(local.get());
2376
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002377 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002378
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002379 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002380 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002381 generator.emitInc(enumeratorIndex.get());
2382 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002383 generator.emitJump(loopStart.get());
2384
2385 generator.emitLabel(scope->breakTarget());
2386 generator.emitJump(end.get());
2387 generator.emitLabel(loopEnd.get());
2388 }
2389
2390 // Generic property loop.
2391 {
2392 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2393 RefPtr<Label> loopStart = generator.newLabel();
2394 RefPtr<Label> loopEnd = generator.newLabel();
2395
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002396 RefPtr<RegisterID> propertyName = generator.newTemporary();
2397
msaboff@apple.comb644c252015-03-24 10:05:21 +00002398 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002399
2400 generator.emitLabel(loopStart.get());
2401 generator.emitLoopHint();
2402
msaboff@apple.comb644c252015-03-24 10:05:21 +00002403 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2404 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2405
2406 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
2407 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2408
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002409 this->emitLoopHeader(generator, propertyName.get());
2410
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002411 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002412
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002413 generator.emitNode(dst, m_statement);
2414
2415 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002416 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002417 generator.emitInc(enumeratorIndex.get());
2418 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
2419 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002420
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002421 generator.emitLabel(scope->breakTarget());
2422 generator.emitJump(end.get());
2423 generator.emitLabel(loopEnd.get());
2424 }
2425
2426 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2427 generator.emitLabel(end.get());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002428 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002429 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002430}
2431
2432void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2433{
2434 this->emitMultiLoopBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002435}
2436
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002437// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002438void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2439{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002440 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002441 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002442 return;
2443 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002444
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002445 RegisterID* forLoopSymbolTable = nullptr;
2446 generator.pushLexicalScope(this, true, &forLoopSymbolTable);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002447 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002448 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002449 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002450 if (m_lexpr->isResolveNode()) {
2451 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002452 Variable var = generator.variable(ident);
2453 if (RegisterID* local = var.local())
2454 generator.emitMove(local, value);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002455 else {
2456 if (generator.isStrictMode())
2457 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002458 RegisterID* scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002459 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002460 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002461 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002462 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00002463 } else if (m_lexpr->isDotAccessorNode()) {
2464 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2465 const Identifier& ident = assignNode->identifier();
2466 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2467
2468 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2469 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002470 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002471 } else if (m_lexpr->isBracketAccessorNode()) {
2472 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
2473 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2474 RegisterID* subscript = generator.emitNode(assignNode->subscript());
2475
2476 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2477 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002478 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002479 } else {
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002480 ASSERT(m_lexpr->isDestructuringNode());
2481 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00002482 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002483 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002484 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002485 generator.emitNode(dst, m_statement);
2486 };
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002487 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
2488 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002489 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002490}
2491
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002492// ------------------------------ ContinueNode ---------------------------------
2493
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002494Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
2495{
2496 if (generator.shouldEmitDebugHooks())
2497 return 0;
2498
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002499 LabelScopePtr scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002500 ASSERT(scope);
2501
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002502 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002503 return 0;
2504
2505 return scope->continueTarget();
2506}
2507
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002508void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002509{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002510 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002511
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002512 LabelScopePtr scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002513 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002514
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002515 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002516 generator.emitJump(scope->continueTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002517
2518 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002519}
2520
2521// ------------------------------ BreakNode ------------------------------------
2522
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002523Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
2524{
2525 if (generator.shouldEmitDebugHooks())
2526 return 0;
2527
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002528 LabelScopePtr scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002529 ASSERT(scope);
2530
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002531 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002532 return 0;
2533
2534 return scope->breakTarget();
2535}
2536
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002537void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002538{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002539 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002540
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002541 LabelScopePtr scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002542 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002543
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002544 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002545 generator.emitJump(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002546
2547 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002548}
2549
2550// ------------------------------ ReturnNode -----------------------------------
2551
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002552void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002553{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002554 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002555 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002556
2557 if (dst == generator.ignoredResult())
2558 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002559
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002560 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002561 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
saambarati1@gmail.com88b7e5b2015-08-05 21:45:20 +00002562 if (generator.isInFinallyBlock()) {
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002563 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002564 generator.emitPopScopes(generator.scopeRegister(), 0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002565 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002566
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002567 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002568 generator.emitReturn(returnRegister.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002569 generator.emitProfileControlFlow(endOffset());
2570 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
2571 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
2572 if (generator.vm()->controlFlowProfiler())
2573 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002574}
2575
2576// ------------------------------ WithNode -------------------------------------
2577
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002578void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002579{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002580 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.com170d6f22012-09-02 21:27:23 +00002581
2582 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002583 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002584 generator.emitPushWithScope(scope.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002585 generator.emitNodeInTailPosition(dst, m_statement);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002586 generator.emitPopWithScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002587}
2588
2589// ------------------------------ CaseClauseNode --------------------------------
2590
2591inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2592{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002593 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002594 if (!m_statements)
2595 return;
2596 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002597}
2598
2599// ------------------------------ CaseBlockNode --------------------------------
2600
2601enum SwitchKind {
2602 SwitchUnset = 0,
2603 SwitchNumber = 1,
2604 SwitchString = 2,
2605 SwitchNeither = 3
2606};
2607
2608static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2609{
2610 for (; list; list = list->getNext()) {
2611 ExpressionNode* clauseExpression = list->getClause()->expr();
2612 literalVector.append(clauseExpression);
2613 if (clauseExpression->isNumber()) {
2614 double value = static_cast<NumberNode*>(clauseExpression)->value();
2615 int32_t intVal = static_cast<int32_t>(value);
2616 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
2617 typeForTable = SwitchNeither;
2618 break;
2619 }
2620 if (intVal < min_num)
2621 min_num = intVal;
2622 if (intVal > max_num)
2623 max_num = intVal;
2624 typeForTable = SwitchNumber;
2625 continue;
2626 }
2627 if (clauseExpression->isString()) {
2628 if (typeForTable & ~SwitchString) {
2629 typeForTable = SwitchNeither;
2630 break;
2631 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00002632 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00002633 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00002634 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002635 if (intVal < min_num)
2636 min_num = intVal;
2637 if (intVal > max_num)
2638 max_num = intVal;
2639 }
2640 typeForTable = SwitchString;
2641 continue;
2642 }
2643 typeForTable = SwitchNeither;
2644 break;
2645 }
2646}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002647
2648static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002649{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002650 size_t length = 0;
2651 for (ClauseListNode* node = list1; node; node = node->getNext())
2652 ++length;
2653 for (ClauseListNode* node = list2; node; node = node->getNext())
2654 ++length;
2655 return length;
2656}
2657
2658SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2659{
2660 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
2661 return SwitchInfo::SwitchNone;
2662
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002663 SwitchKind typeForTable = SwitchUnset;
2664 bool singleCharacterSwitch = true;
2665
2666 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2667 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2668
2669 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2670 return SwitchInfo::SwitchNone;
2671
2672 if (typeForTable == SwitchNumber) {
2673 int32_t range = max_num - min_num;
2674 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2675 return SwitchInfo::SwitchImmediate;
2676 return SwitchInfo::SwitchNone;
2677 }
2678
2679 ASSERT(typeForTable == SwitchString);
2680
2681 if (singleCharacterSwitch) {
2682 int32_t range = max_num - min_num;
2683 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2684 return SwitchInfo::SwitchCharacter;
2685 }
2686
2687 return SwitchInfo::SwitchString;
2688}
2689
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002690void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002691{
2692 RefPtr<Label> defaultLabel;
2693 Vector<RefPtr<Label>, 8> labelVector;
2694 Vector<ExpressionNode*, 8> literalVector;
2695 int32_t min_num = std::numeric_limits<int32_t>::max();
2696 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002697 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002698
2699 if (switchType != SwitchInfo::SwitchNone) {
2700 // Prepare the various labels
2701 for (uint32_t i = 0; i < literalVector.size(); i++)
2702 labelVector.append(generator.newLabel());
2703 defaultLabel = generator.newLabel();
2704 generator.beginSwitch(switchExpression, switchType);
2705 } else {
2706 // Setup jumps
2707 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2708 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2709 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2710 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2711 labelVector.append(generator.newLabel());
2712 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2713 }
2714
2715 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2716 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2717 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2718 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2719 labelVector.append(generator.newLabel());
2720 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2721 }
2722 defaultLabel = generator.newLabel();
2723 generator.emitJump(defaultLabel.get());
2724 }
2725
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002726 size_t i = 0;
2727 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2728 generator.emitLabel(labelVector[i++].get());
2729 list->getClause()->emitBytecode(generator, dst);
2730 }
2731
2732 if (m_defaultClause) {
2733 generator.emitLabel(defaultLabel.get());
2734 m_defaultClause->emitBytecode(generator, dst);
2735 }
2736
2737 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2738 generator.emitLabel(labelVector[i++].get());
2739 list->getClause()->emitBytecode(generator, dst);
2740 }
2741 if (!m_defaultClause)
2742 generator.emitLabel(defaultLabel.get());
2743
2744 ASSERT(i == labelVector.size());
2745 if (switchType != SwitchInfo::SwitchNone) {
2746 ASSERT(labelVector.size() == literalVector.size());
2747 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2748 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002749}
2750
2751// ------------------------------ SwitchNode -----------------------------------
2752
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002753void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002754{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002755 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002756
oliver@apple.com6a976452013-03-11 21:02:39 +00002757 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002758
2759 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002760
2761 generator.pushLexicalScope(this, false);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002762 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002763 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002764
2765 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002766 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002767}
2768
2769// ------------------------------ LabelNode ------------------------------------
2770
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002771void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002772{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002773 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002774
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002775 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002776
oliver@apple.com6a976452013-03-11 21:02:39 +00002777 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002778 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002779
2780 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002781}
2782
2783// ------------------------------ ThrowNode ------------------------------------
2784
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002785void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002786{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002787 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002788
2789 if (dst == generator.ignoredResult())
2790 dst = 0;
2791 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002792 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002793 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002794
2795 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002796}
2797
2798// ------------------------------ TryNode --------------------------------------
2799
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002800void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002801{
2802 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2803 // optimizer knows they may be jumped to from anywhere.
2804
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002805 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002806
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002807 ASSERT(m_catchBlock || m_finallyBlock);
2808
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002809 RefPtr<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002810 generator.emitLabel(tryStartLabel.get());
2811
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002812 if (m_finallyBlock)
2813 generator.pushFinallyContext(m_finallyBlock);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002814 TryData* tryData = generator.pushTry(tryStartLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002815
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002816 generator.emitNode(dst, m_tryBlock);
2817
2818 if (m_catchBlock) {
2819 RefPtr<Label> catchEndLabel = generator.newLabel();
2820
2821 // Normal path: jump over the catch block.
2822 generator.emitJump(catchEndLabel.get());
2823
2824 // Uncaught exception path: the catch block.
2825 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002826 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
2827 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
2828 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), here.get(), HandlerType::Catch);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002829
2830 if (m_finallyBlock) {
2831 // If the catch block throws an exception and we have a finally block, then the finally
2832 // block should "catch" that exception.
2833 tryData = generator.pushTry(here.get());
2834 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002835
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002836 generator.emitPushCatchScope(m_thrownValueIdent, thrownValueRegister.get(), m_catchEnvironment);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002837 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002838 if (m_finallyBlock)
2839 generator.emitNode(dst, m_catchBlock);
2840 else
2841 generator.emitNodeInTailPosition(dst, m_catchBlock);
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00002842 generator.emitPopCatchScope(m_catchEnvironment);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002843 generator.emitLabel(catchEndLabel.get());
2844 }
2845
2846 if (m_finallyBlock) {
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002847 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2848
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002849 generator.popFinallyContext();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002850
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002851 RefPtr<Label> finallyEndLabel = generator.newLabel();
2852
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002853 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002854
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002855 // Normal path: run the finally code, and jump to the end.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002856 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002857 generator.emitNodeInTailPosition(dst, m_finallyBlock);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002858 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002859 generator.emitJump(finallyEndLabel.get());
2860
2861 // Uncaught exception path: invoke the finally block, then re-throw the exception.
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002862 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
2863 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
2864 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002865 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002866 generator.emitNodeInTailPosition(dst, m_finallyBlock);
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002867 generator.emitThrow(exceptionRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002868
2869 generator.emitLabel(finallyEndLabel.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002870 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002871 } else
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002872 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002873
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002874}
2875
2876// ------------------------------ ScopeNode -----------------------------
2877
2878inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2879{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002880 if (!m_statements)
2881 return;
2882 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002883}
2884
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002885static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
2886{
2887 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
2888
2889 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2890 generator.emitLoad(dstRegister.get(), jsUndefined());
2891 generator.emitProfileControlFlow(scopeNode.startStartOffset());
2892 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
2893
2894 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
2895 generator.emitEnd(dstRegister.get());
2896}
2897
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002898// ------------------------------ ProgramNode -----------------------------
2899
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002900void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002901{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002902 emitProgramNodeBytecode(generator, *this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002903}
2904
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00002905// ------------------------------ ModuleProgramNode --------------------
2906
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002907void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00002908{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002909 emitProgramNodeBytecode(generator, *this);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00002910}
2911
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002912// ------------------------------ EvalNode -----------------------------
2913
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002914void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002915{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002916 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002917
2918 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2919 generator.emitLoad(dstRegister.get(), jsUndefined());
2920 emitStatementsBytecode(generator, dstRegister.get());
2921
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002922 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002923 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002924}
2925
ggaren@apple.come7afe402015-08-10 20:24:35 +00002926// ------------------------------ FunctionNode -----------------------------
ggaren@apple.com6f851d72014-12-04 23:47:49 +00002927
2928void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002929{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002930 if (generator.vm()->typeProfiler()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002931 for (size_t i = 0; i < m_parameters->size(); i++) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002932 // Destructuring parameters are handled in destructuring nodes.
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00002933 if (!m_parameters->at(i).first->isBindingNode())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002934 continue;
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00002935 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002936 RegisterID reg(CallFrame::argumentOffset(i));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002937 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002938 }
2939 }
2940
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002941 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002942 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002943 emitStatementsBytecode(generator, generator.ignoredResult());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002944
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002945 StatementNode* singleStatement = this->singleStatement();
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002946 ReturnNode* returnNode = 0;
2947
2948 // Check for a return statement at the end of a function composed of a single block.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002949 if (singleStatement && singleStatement->isBlock()) {
2950 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2951 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002952 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002953 }
2954
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002955 // If there is no return we must automatically insert one.
2956 if (!returnNode) {
2957 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002958 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
mark.lam@apple.comfa35e782013-11-19 21:55:16 +00002959 ASSERT(startOffset() >= lineStartOffset());
2960 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002961 generator.emitReturn(r0);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002962 return;
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002963 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002964}
2965
2966// ------------------------------ FuncDeclNode ---------------------------------
2967
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002968void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002969{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002970}
2971
2972// ------------------------------ FuncExprNode ---------------------------------
2973
2974RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2975{
2976 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2977}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00002978
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00002979// ------------------------------ ArrowFuncExprNode ---------------------------------
2980
2981RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2982{
2983 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
2984}
2985
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00002986#if ENABLE(ES6_CLASS_SYNTAX)
2987// ------------------------------ ClassDeclNode ---------------------------------
2988
2989void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2990{
2991 generator.emitNode(dst, m_classDeclaration);
2992}
2993
2994// ------------------------------ ClassExprNode ---------------------------------
2995
2996RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2997{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002998 RefPtr<RegisterID> superclass;
2999 if (m_classHeritage) {
3000 superclass = generator.newTemporary();
3001 generator.emitNode(superclass.get(), m_classHeritage);
3002 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003003
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003004 RefPtr<RegisterID> constructor;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003005
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003006 // FIXME: Make the prototype non-configurable & non-writable.
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003007 if (m_constructorExpression)
3008 constructor = generator.emitNode(dst, m_constructorExpression);
3009 else {
3010 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
3011 m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base, m_name);
3012 }
3013
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003014 const auto& propertyNames = generator.propertyNames();
3015 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003016
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003017 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003018 RefPtr<RegisterID> protoParent = generator.newTemporary();
3019 generator.emitLoad(protoParent.get(), jsNull());
3020
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003021 RefPtr<RegisterID> tempRegister = generator.newTemporary();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003022
3023 // FIXME: Throw TypeError if it's a generator function.
3024 RefPtr<Label> superclassIsUndefinedLabel = generator.newLabel();
3025 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
3026
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003027 RefPtr<Label> superclassIsNullLabel = generator.newLabel();
3028 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3029
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003030 RefPtr<Label> superclassIsObjectLabel = generator.newLabel();
3031 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003032 generator.emitLabel(superclassIsUndefinedLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003033 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3034 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003035 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
3036
3037 RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
3038 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
3039 generator.emitThrowTypeError(ASCIILiteral("The superclass's prototype is not an object."));
3040 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
3041
3042 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003043 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003044 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
3045
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003046 emitPutHomeObject(generator, constructor.get(), prototype.get());
3047 }
3048
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003049 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.constructor);
3050 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
3051 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
3052
3053 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.prototype);
3054 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
3055
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003056 if (m_staticMethods)
3057 generator.emitNode(constructor.get(), m_staticMethods);
3058
3059 if (m_instanceMethods)
3060 generator.emitNode(prototype.get(), m_instanceMethods);
3061
3062 return generator.moveToDestinationIfNeeded(dst, constructor.get());
3063}
3064#endif
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003065
3066// ------------------------------ ImportDeclarationNode -----------------------
3067
3068void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3069{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003070 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003071}
3072
3073// ------------------------------ ExportAllDeclarationNode --------------------
3074
3075void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3076{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003077 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003078}
3079
3080// ------------------------------ ExportDefaultDeclarationNode ----------------
3081
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003082void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003083{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003084 ASSERT(m_declaration);
3085 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003086}
3087
3088// ------------------------------ ExportLocalDeclarationNode ------------------
3089
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003090void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003091{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003092 ASSERT(m_declaration);
3093 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003094}
3095
3096// ------------------------------ ExportNamedDeclarationNode ------------------
3097
3098void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3099{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003100 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003101}
3102
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003103// ------------------------------ DestructuringAssignmentNode -----------------
3104RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
oliver@apple.comd055db62013-10-02 19:11:04 +00003105{
3106 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
3107 return result;
3108 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
3109 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00003110 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003111 return generator.moveToDestinationIfNeeded(dst, initializer.get());
3112}
3113
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003114static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
3115{
3116 ASSERT(defaultValue);
3117 RefPtr<Label> isNotUndefined = generator.newLabel();
3118 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
3119 generator.emitNode(maybeUndefined, defaultValue);
3120 generator.emitLabel(isNotUndefined.get());
3121}
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003122
oliver@apple.com47784d62013-10-25 21:31:36 +00003123void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003124{
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003125 RefPtr<RegisterID> iterator = generator.newTemporary();
3126 {
3127 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
3128 CallArguments args(generator, nullptr);
3129 generator.emitMove(args.thisRegister(), rhs);
3130 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
3131 }
3132
utatane.tea@gmail.coma5c94332015-06-23 00:51:44 +00003133 if (m_targetPatterns.isEmpty()) {
3134 generator.emitIteratorClose(iterator.get(), this);
3135 return;
3136 }
3137
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003138 RefPtr<RegisterID> done;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003139 for (auto& target : m_targetPatterns) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003140 switch (target.bindingType) {
3141 case BindingType::Elision:
3142 case BindingType::Element: {
3143 RefPtr<Label> iterationSkipped = generator.newLabel();
3144 if (!done)
3145 done = generator.newTemporary();
3146 else
3147 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003148
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003149 RefPtr<RegisterID> value = generator.newTemporary();
3150 generator.emitIteratorNext(value.get(), iterator.get(), this);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003151 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003152 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
3153 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003154
3155 {
3156 RefPtr<Label> valueIsSet = generator.newLabel();
3157 generator.emitJump(valueIsSet.get());
3158 generator.emitLabel(iterationSkipped.get());
3159 generator.emitLoad(value.get(), jsUndefined());
3160 generator.emitLabel(valueIsSet.get());
3161 }
3162
3163 if (target.bindingType == BindingType::Element) {
3164 if (target.defaultValue)
3165 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
3166 target.pattern->bindValue(generator, value.get());
3167 }
3168 break;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003169 }
3170
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003171 case BindingType::RestElement: {
3172 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
3173
3174 RefPtr<Label> iterationDone = generator.newLabel();
3175 if (!done)
3176 done = generator.newTemporary();
3177 else
3178 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3179
3180 RefPtr<RegisterID> index = generator.newTemporary();
3181 generator.emitLoad(index.get(), jsNumber(0));
3182 RefPtr<Label> loopStart = generator.newLabel();
3183 generator.emitLabel(loopStart.get());
3184
3185 RefPtr<RegisterID> value = generator.newTemporary();
3186 generator.emitIteratorNext(value.get(), iterator.get(), this);
3187 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
3188 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3189 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
3190
3191 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
3192 generator.emitInc(index.get());
3193 generator.emitJump(loopStart.get());
3194
3195 generator.emitLabel(iterationDone.get());
3196 target.pattern->bindValue(generator, array.get());
3197 break;
3198 }
3199 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003200 }
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003201
3202 RefPtr<Label> iteratorClosed = generator.newLabel();
3203 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
3204 generator.emitIteratorClose(iterator.get(), this);
3205 generator.emitLabel(iteratorClosed.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003206}
3207
3208RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
3209{
oliver@apple.comd055db62013-10-02 19:11:04 +00003210 if (!rhs->isSimpleArray())
3211 return 0;
oliver@apple.com47784d62013-10-25 21:31:36 +00003212
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003213 RefPtr<RegisterID> resultRegister;
3214 if (dst && dst != generator.ignoredResult())
3215 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00003216 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
3217 Vector<ExpressionNode*> elements;
3218 for (; elementNodes; elementNodes = elementNodes->next())
3219 elements.append(elementNodes->value());
3220 if (m_targetPatterns.size() != elements.size())
3221 return 0;
3222 Vector<RefPtr<RegisterID>> registers;
3223 registers.reserveCapacity(m_targetPatterns.size());
3224 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3225 registers.uncheckedAppend(generator.newTemporary());
3226 generator.emitNode(registers.last().get(), elements[i]);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003227 if (m_targetPatterns[i].defaultValue)
3228 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003229 if (resultRegister)
3230 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003231 }
3232
3233 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003234 if (m_targetPatterns[i].pattern)
3235 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003236 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003237 if (resultRegister)
3238 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00003239 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00003240}
3241
3242void ArrayPatternNode::toString(StringBuilder& builder) const
3243{
3244 builder.append('[');
3245 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003246 const auto& target = m_targetPatterns[i];
3247
3248 switch (target.bindingType) {
3249 case BindingType::Elision:
oliver@apple.comd055db62013-10-02 19:11:04 +00003250 builder.append(',');
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003251 break;
3252
3253 case BindingType::Element:
3254 target.pattern->toString(builder);
3255 if (i < m_targetPatterns.size() - 1)
3256 builder.append(',');
3257 break;
3258
3259 case BindingType::RestElement:
3260 builder.append("...");
3261 target.pattern->toString(builder);
3262 break;
oliver@apple.comd055db62013-10-02 19:11:04 +00003263 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003264 }
3265 builder.append(']');
3266}
3267
3268void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3269{
3270 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.comc497d152015-07-17 18:48:30 +00003271 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
oliver@apple.comd055db62013-10-02 19:11:04 +00003272 node->collectBoundIdentifiers(identifiers);
3273 }
3274}
3275
3276void ObjectPatternNode::toString(StringBuilder& builder) const
3277{
3278 builder.append('{');
3279 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003280 if (m_targetPatterns[i].wasString)
akling@apple.coma9904fb2015-05-08 08:44:23 +00003281 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003282 else
oliver@apple.comd055db62013-10-02 19:11:04 +00003283 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00003284 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00003285 m_targetPatterns[i].pattern->toString(builder);
3286 if (i < m_targetPatterns.size() - 1)
3287 builder.append(',');
3288 }
3289 builder.append('}');
3290}
3291
oliver@apple.com47784d62013-10-25 21:31:36 +00003292void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003293{
3294 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3295 auto& target = m_targetPatterns[i];
3296 RefPtr<RegisterID> temp = generator.newTemporary();
3297 generator.emitGetById(temp.get(), rhs, target.propertyName);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003298 if (target.defaultValue)
3299 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
oliver@apple.com47784d62013-10-25 21:31:36 +00003300 target.pattern->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003301 }
3302}
3303
3304void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3305{
3306 for (size_t i = 0; i < m_targetPatterns.size(); i++)
3307 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
3308}
3309
oliver@apple.com47784d62013-10-25 21:31:36 +00003310void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003311{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003312 Variable var = generator.variable(m_boundProperty);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003313 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003314 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003315 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3316 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003317 if (isReadOnly) {
3318 generator.emitReadOnlyExceptionIfNeeded(var);
3319 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00003320 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003321 generator.emitMove(local, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003322 generator.emitProfileType(local, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003323 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003324 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003325 return;
3326 }
3327 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003328 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003329 RegisterID* scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003330 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003331 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3332 generator.emitTDZCheckIfNecessary(var, nullptr, scope);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003333 if (isReadOnly) {
3334 generator.emitReadOnlyExceptionIfNeeded(var);
3335 return;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003336 }
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00003337 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound,
3338 m_bindingContext == AssignmentContext::ConstDeclarationStatement || m_bindingContext == AssignmentContext::DeclarationStatement ? Initialization : NotInitialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003339 generator.emitProfileType(value, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003340 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003341 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003342 return;
3343}
3344
3345void BindingNode::toString(StringBuilder& builder) const
3346{
3347 builder.append(m_boundProperty.string());
3348}
3349
3350void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3351{
3352 identifiers.append(m_boundProperty);
3353}
oliver@apple.com72f8a822013-10-17 01:02:34 +00003354
3355RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3356{
3357 RELEASE_ASSERT_NOT_REACHED();
3358 return 0;
3359}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003360
3361} // namespace JSC