blob: 312a8c7ace0415608bd3747deda7868e5bbd0f52 [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
utatane.tea@gmail.comc5ccd8e2015-10-11 18:46:52 +0000170 return generator.emitGetById(generator.finalDestination(dst), &callee, generator.propertyNames().underscoreProto);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000171}
172
173static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
174{
175 RegisterID callee;
176 callee.setIndex(JSStack::Callee);
177
178 RefPtr<RegisterID> homeObject = generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
179 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
180}
181
commit-queue@webkit.org17f99e42015-07-21 18:18:42 +0000182// ------------------------------ NewTargetNode ----------------------------------
183
184RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
185{
186 if (dst == generator.ignoredResult())
187 return nullptr;
188
189 return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
190}
191
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000192// ------------------------------ ResolveNode ----------------------------------
193
194bool ResolveNode::isPure(BytecodeGenerator& generator) const
195{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000196 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000197}
198
199RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
200{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000201 Variable var = generator.variable(m_ident);
202 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000203 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000204 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000205 return nullptr;
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000206
207 generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000208 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000209 }
210
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000211 JSTextPosition divot = m_start + m_ident.length();
212 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000213 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000214 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000215 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000216 generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000217 generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000218 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000219}
220
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000221// ------------------------------ TemplateStringNode -----------------------------------
222
223RegisterID* TemplateStringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
224{
225 if (dst == generator.ignoredResult())
226 return nullptr;
227 return generator.emitLoad(dst, JSValue(generator.addStringConstant(cooked())));
228}
229
230// ------------------------------ TemplateLiteralNode -----------------------------------
231
232RegisterID* TemplateLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
233{
234 if (!m_templateExpressions) {
235 TemplateStringNode* templateString = m_templateStrings->value();
236 ASSERT_WITH_MESSAGE(!m_templateStrings->next(), "Only one template element exists because there's no expression in a given template literal.");
237 return generator.emitNode(dst, templateString);
238 }
239
240 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
241
242 TemplateStringListNode* templateString = m_templateStrings;
243 TemplateExpressionListNode* templateExpression = m_templateExpressions;
244 for (; templateExpression; templateExpression = templateExpression->next(), templateString = templateString->next()) {
245 // Evaluate TemplateString.
246 if (!templateString->value()->cooked().isEmpty()) {
247 temporaryRegisters.append(generator.newTemporary());
248 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
249 }
250
251 // Evaluate Expression.
252 temporaryRegisters.append(generator.newTemporary());
253 generator.emitNode(temporaryRegisters.last().get(), templateExpression->value());
254 generator.emitToString(temporaryRegisters.last().get(), temporaryRegisters.last().get());
255 }
256
257 // Evaluate tail TemplateString.
258 if (!templateString->value()->cooked().isEmpty()) {
259 temporaryRegisters.append(generator.newTemporary());
260 generator.emitNode(temporaryRegisters.last().get(), templateString->value());
261 }
262
263 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
264}
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000265
266// ------------------------------ TaggedTemplateNode -----------------------------------
267
268RegisterID* TaggedTemplateNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
269{
270 ExpectedFunction expectedFunction = NoExpectedFunction;
271 RefPtr<RegisterID> tag = nullptr;
272 RefPtr<RegisterID> base = nullptr;
273 if (!m_tag->isLocation()) {
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000274 tag = generator.newTemporary();
275 tag = generator.emitNode(tag.get(), m_tag);
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000276 } else if (m_tag->isResolveNode()) {
277 ResolveNode* resolve = static_cast<ResolveNode*>(m_tag);
278 const Identifier& identifier = resolve->identifier();
279 expectedFunction = generator.expectedFunctionForIdentifier(identifier);
280
281 Variable var = generator.variable(identifier);
282 if (RegisterID* local = var.local())
283 tag = generator.emitMove(generator.newTemporary(), local);
284 else {
285 tag = generator.newTemporary();
286 base = generator.newTemporary();
287
288 JSTextPosition newDivot = divotStart() + identifier.length();
289 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
290 generator.moveToDestinationIfNeeded(base.get(), generator.emitResolveScope(base.get(), var));
291 generator.emitGetFromScope(tag.get(), base.get(), var, ThrowIfNotFound);
292 }
293 } else if (m_tag->isBracketAccessorNode()) {
294 BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000295 base = generator.newTemporary();
296 base = generator.emitNode(base.get(), bracket->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000297 RefPtr<RegisterID> property = generator.emitNode(bracket->subscript());
298 tag = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
299 } else {
300 ASSERT(m_tag->isDotAccessorNode());
301 DotAccessorNode* dot = static_cast<DotAccessorNode*>(m_tag);
utatane.tea@gmail.coma26653e2015-05-14 19:58:00 +0000302 base = generator.newTemporary();
303 base = generator.emitNode(base.get(), dot->base());
utatane.tea@gmail.comd68d2482015-05-14 16:07:54 +0000304 tag = generator.emitGetById(generator.newTemporary(), base.get(), dot->identifier());
305 }
306
307 RefPtr<RegisterID> templateObject = generator.emitGetTemplateObject(generator.newTemporary(), this);
308
309 unsigned expressionsCount = 0;
310 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
311 ++expressionsCount;
312
313 CallArguments callArguments(generator, nullptr, 1 + expressionsCount);
314 if (base)
315 generator.emitMove(callArguments.thisRegister(), base.get());
316 else
317 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
318
319 unsigned argumentIndex = 0;
320 generator.emitMove(callArguments.argumentRegister(argumentIndex++), templateObject.get());
321 for (TemplateExpressionListNode* templateExpression = m_templateLiteral->templateExpressions(); templateExpression; templateExpression = templateExpression->next())
322 generator.emitNode(callArguments.argumentRegister(argumentIndex++), templateExpression->value());
323
324 return generator.emitCall(generator.finalDestination(dst, tag.get()), tag.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
325}
utatane.tea@gmail.com4014aea2015-04-27 00:27:28 +0000326
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000327// ------------------------------ ArrayNode ------------------------------------
328
329RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
330{
331 // FIXME: Should we put all of this code into emitNewArray?
332
333 unsigned length = 0;
334 ElementNode* firstPutElement;
335 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000336 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000337 break;
338 ++length;
339 }
340
341 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000342 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000343
oliver@apple.coma991d692011-06-14 23:39:25 +0000344 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000345 ElementNode* n = firstPutElement;
346 for (; n; n = n->next()) {
347 if (n->value()->isSpreadExpression())
348 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000349 RegisterID* value = generator.emitNode(n->value());
350 length += n->elision();
351 generator.emitPutByIndex(array.get(), length++, value);
352 }
353
354 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000355 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000356 generator.emitPutById(array.get(), generator.propertyNames().length, value);
357 }
358
359 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000360
361handleSpread:
362 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
363 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
364 {
oliver@apple.come050d642013-10-19 00:09:28 +0000365 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000366 generator.emitInc(index.get());
367 };
368 for (; n; n = n->next()) {
369 if (n->elision())
370 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
371 if (n->value()->isSpreadExpression()) {
372 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
373 generator.emitEnumeration(spread, spread->expression(), spreader);
374 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000375 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000376 generator.emitInc(index.get());
377 }
378 }
379
380 if (m_elision) {
381 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
382 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
383 }
384 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000385}
386
387bool ArrayNode::isSimpleArray() const
388{
389 if (m_elision || m_optional)
390 return false;
391 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
392 if (ptr->elision())
393 return false;
394 }
395 return true;
396}
397
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000398ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000399{
400 ASSERT(!m_elision && !m_optional);
401 ElementNode* ptr = m_element;
402 if (!ptr)
403 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000404 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000405 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000406 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000407 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000408 ArgumentListNode* tail = head;
409 ptr = ptr->next();
410 for (; ptr; ptr = ptr->next()) {
411 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000412 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000413 }
414 return head;
415}
416
417// ------------------------------ ObjectLiteralNode ----------------------------
418
419RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
420{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000421 if (!m_list) {
422 if (dst == generator.ignoredResult())
423 return 0;
424 return generator.emitNewObject(generator.finalDestination(dst));
425 }
426 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
427 generator.emitNode(newObj.get(), m_list);
428 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000429}
430
431// ------------------------------ PropertyListNode -----------------------------
432
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000433static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
434{
435 generator.emitPutById(function, generator.propertyNames().homeObjectPrivateName, homeObject);
436}
437
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000438RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
439{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000440 // Fast case: this loop just handles regular value properties.
441 PropertyListNode* p = this;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000442 for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000443 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000444
445 // Were there any get/set properties?
446 if (p) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000447 // Build a list of getter/setter pairs to try to put them at the same time. If we encounter
448 // a computed property, just emit everything as that may override previous values.
449 bool hasComputedProperty = false;
450
barraclough@apple.com09a55682012-01-30 18:28:39 +0000451 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
utatane.tea@gmail.com8268d392015-05-23 18:41:53 +0000452 typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000453 GetterSetterMap map;
454
455 // Build a map, pairing get/set values together.
456 for (PropertyListNode* q = p; q; q = q->m_next) {
457 PropertyNode* node = q->m_node;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000458 if (node->m_type & PropertyNode::Computed) {
459 hasComputedProperty = true;
460 break;
461 }
462 if (node->m_type & PropertyNode::Constant)
barraclough@apple.com09a55682012-01-30 18:28:39 +0000463 continue;
464
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000465 // Duplicates are possible.
466 GetterSetterPair pair(node, static_cast<PropertyNode*>(nullptr));
oliver@apple.com72d38322013-10-21 19:23:24 +0000467 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000468 if (!result.isNewEntry) {
469 if (result.iterator->value.first->m_type == node->m_type)
470 result.iterator->value.first = node;
471 else
472 result.iterator->value.second = node;
473 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000474 }
475
476 // Iterate over the remaining properties in the list.
477 for (; p; p = p->m_next) {
478 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000479
480 // Handle regular values.
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000481 if (node->m_type & PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000482 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000483 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000484 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000485
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000486 RefPtr<RegisterID> value = generator.emitNode(node->m_assign);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000487 bool isClassProperty = node->needsSuperBinding();
488 if (isClassProperty)
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000489 emitPutHomeObject(generator, value.get(), dst);
490 unsigned attribute = isClassProperty ? (Accessor | DontEnum) : Accessor;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000491
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000492 ASSERT(node->m_type & (PropertyNode::Getter | PropertyNode::Setter));
493
494 // This is a get/set property which may be overridden by a computed property later.
495 if (hasComputedProperty) {
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000496 // Computed accessors.
497 if (node->m_type & PropertyNode::Computed) {
498 RefPtr<RegisterID> propertyName = generator.emitNode(node->m_expression);
499 if (node->m_type & PropertyNode::Getter)
500 generator.emitPutGetterByVal(dst, propertyName.get(), attribute, value.get());
501 else
502 generator.emitPutSetterByVal(dst, propertyName.get(), attribute, value.get());
503 continue;
504 }
505
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000506 if (node->m_type & PropertyNode::Getter)
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000507 generator.emitPutGetterById(dst, *node->name(), attribute, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000508 else
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000509 generator.emitPutSetterById(dst, *node->name(), attribute, value.get());
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000510 continue;
511 }
512
513 // This is a get/set property pair.
oliver@apple.com72d38322013-10-21 19:23:24 +0000514 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000515 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000516 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000517
518 // Was this already generated as a part of its partner?
519 if (pair.second == node)
520 continue;
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000521
barraclough@apple.com09a55682012-01-30 18:28:39 +0000522 // Generate the paired node now.
523 RefPtr<RegisterID> getterReg;
524 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000525 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000526
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000527 if (node->m_type & PropertyNode::Getter) {
barraclough@apple.com09a55682012-01-30 18:28:39 +0000528 getterReg = value;
529 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000530 ASSERT(pair.second->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000531 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000532 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000533 } else {
534 setterReg = generator.newTemporary();
535 generator.emitLoad(setterReg.get(), jsUndefined());
536 }
537 } else {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000538 ASSERT(node->m_type & PropertyNode::Setter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000539 setterReg = value;
540 if (pair.second) {
commit-queue@webkit.orgfb471b42015-05-14 01:32:25 +0000541 ASSERT(pair.second->m_type & PropertyNode::Getter);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000542 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000543 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000544 } else {
545 getterReg = generator.newTemporary();
546 generator.emitLoad(getterReg.get(), jsUndefined());
547 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000548 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000549
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000550 ASSERT(!pair.second || isClassProperty == pair.second->needsSuperBinding());
551 if (isClassProperty && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000552 emitPutHomeObject(generator, secondReg, dst);
553
utatane.tea@gmail.comf0153d02015-09-08 19:43:58 +0000554 generator.emitPutGetterSetter(dst, *node->name(), attribute, getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000555 }
556 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000557
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000558 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000559}
560
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000561void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
562{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000563 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000564 if (node.needsSuperBinding()) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000565 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000566
567 RefPtr<RegisterID> propertyNameRegister;
568 if (node.name())
569 propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node.name());
570 else
571 propertyNameRegister = generator.emitNode(node.m_expression);
572
573 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(),
574 value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
575 return;
576 }
utatane.tea@gmail.comac224502015-05-26 17:26:40 +0000577 if (const auto* identifier = node.name()) {
578 Optional<uint32_t> optionalIndex = parseIndex(*identifier);
579 if (!optionalIndex) {
580 generator.emitDirectPutById(newObj, *identifier, value.get(), node.putType());
581 return;
582 }
583
584 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(optionalIndex.value()));
585 generator.emitDirectPutByVal(newObj, index.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000586 return;
587 }
588 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000589 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000590}
591
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000592// ------------------------------ BracketAccessorNode --------------------------------
593
594RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
595{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000596 if (m_base->isSuperNode()) {
597 // FIXME: Should we generate the profiler info?
598 if (m_subscript->isString()) {
599 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
600 return generator.emitGetById(generator.finalDestination(dst), emitSuperBaseForCallee(generator), id);
601 }
602 return generator.emitGetByVal(generator.finalDestination(dst), emitSuperBaseForCallee(generator), generator.emitNode(m_subscript));
603 }
604
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000605 RegisterID* ret;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000606 RegisterID* finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000607
608 if (m_subscript->isString()) {
609 RefPtr<RegisterID> base = generator.emitNode(m_base);
610 ret = generator.emitGetById(finalDest, base.get(), static_cast<StringNode*>(m_subscript)->value());
611 } else {
612 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
613 RegisterID* property = generator.emitNode(m_subscript);
614 ret = generator.emitGetByVal(finalDest, base.get(), property);
615 }
616
617 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
618
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000619 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000620 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000621}
622
623// ------------------------------ DotAccessorNode --------------------------------
624
625RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
626{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000627 RefPtr<RegisterID> base = m_base->isSuperNode() ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000628 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000629 RegisterID* finalDest = generator.finalDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000630 RegisterID* ret = generator.emitGetById(finalDest, base.get(), m_ident);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000631 generator.emitProfileType(finalDest, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000632 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000633}
634
635// ------------------------------ ArgumentListNode -----------------------------
636
637RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
638{
639 ASSERT(m_expr);
640 return generator.emitNode(dst, m_expr);
641}
642
643// ------------------------------ NewExprNode ----------------------------------
644
645RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
646{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000647 ExpectedFunction expectedFunction;
648 if (m_expr->isResolveNode())
649 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
650 else
651 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000652 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000653 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000654 CallArguments callArguments(generator, m_args);
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000655 generator.emitMove(callArguments.thisRegister(), func.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000656 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000657}
658
oliver@apple.com72f8a822013-10-17 01:02:34 +0000659CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000660 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000661 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000662{
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +0000663 if (generator.shouldEmitProfileHooks())
664 m_profileHookRegister = generator.newTemporary();
ggaren@apple.com50c5ac22011-11-14 23:16:27 +0000665
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000666 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000667 if (argumentsNode) {
668 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
669 ++argumentCountIncludingThis;
670 }
671
672 m_argv.grow(argumentCountIncludingThis);
673 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
674 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000675 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 +0000676 }
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +0000677
678 // We need to ensure that the frame size is stack-aligned
679 while ((JSStack::CallFrameHeaderSize + m_argv.size()) % stackAlignmentRegisters()) {
680 m_argv.insert(0, generator.newTemporary());
681 m_padding++;
682 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000683
684 while (stackOffset() % stackAlignmentRegisters()) {
685 m_argv.insert(0, generator.newTemporary());
686 m_padding++;
687 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000688}
689
690// ------------------------------ EvalFunctionCallNode ----------------------------------
691
692RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
693{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000694 Variable var = generator.variable(generator.propertyNames().eval);
695 if (RegisterID* local = var.local()) {
696 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000697 CallArguments callArguments(generator, m_args);
698 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000699 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000700 }
701
702 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000703 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000704 JSTextPosition newDivot = divotStart() + 4;
705 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000706 generator.moveToDestinationIfNeeded(
707 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000708 generator.emitResolveScope(callArguments.thisRegister(), var));
709 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000710 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000711}
712
713// ------------------------------ FunctionCallValueNode ----------------------------------
714
715RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
716{
717 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000718 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000719 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000720 if (m_expr->isSuperNode()) {
rniwa@webkit.orge6f83492015-03-13 23:01:51 +0000721 ASSERT(generator.isConstructor());
722 ASSERT(generator.constructorKind() == ConstructorKind::Derived);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000723 generator.emitMove(callArguments.thisRegister(), generator.newTarget());
724 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
725 generator.emitMove(generator.thisRegister(), ret);
726 return ret;
727 }
oliver@apple.com64126552010-10-18 18:32:39 +0000728 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000729 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000730 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000731 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000732}
733
734// ------------------------------ FunctionCallResolveNode ----------------------------------
735
736RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
737{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000738 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000739
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000740 Variable var = generator.variable(m_ident);
741 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000742 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000743 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000744 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000745 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000746 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000747 // This passes NoExpectedFunction because we expect that if the function is in a
748 // local variable, then it's not one of our built-in constructors.
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000749 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000750 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000751 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000752 }
753
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000754 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000755 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000756 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000757
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000758 JSTextPosition newDivot = divotStart() + m_ident.length();
759 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000760 generator.moveToDestinationIfNeeded(
761 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000762 generator.emitResolveScope(callArguments.thisRegister(), var));
763 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +0000764 generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000765 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000766 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000767 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000768}
769
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000770// ------------------------------ BytecodeIntrinsicNode ----------------------------------
771
772RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
773{
774 return (this->*m_emitter)(generator, dst);
775}
776
youenn.fablet@crf.canon.fr5f0b7be2015-11-09 14:15:21 +0000777RegisterID* BytecodeIntrinsicNode::emit_intrinsic_assert(BytecodeGenerator& generator, RegisterID* dst)
778{
779#ifndef NDEBUG
780 ArgumentListNode* node = m_args->m_listNode;
781 RefPtr<RegisterID> condition = generator.emitNode(node);
782 generator.emitAssert(condition.get(), node->firstLine());
783 return dst;
784#else
785 UNUSED_PARAM(generator);
786 return dst;
787#endif
788}
789
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000790RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
791{
792 ArgumentListNode* node = m_args->m_listNode;
793 RefPtr<RegisterID> base = generator.emitNode(node);
794 node = node->m_next;
795 RefPtr<RegisterID> index = generator.emitNode(node);
796 node = node->m_next;
797 RefPtr<RegisterID> value = generator.emitNode(node);
798
799 ASSERT(!node->m_next);
800
801 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
802}
803
utatane.tea@gmail.com965344f2015-05-13 16:48:33 +0000804RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toString(BytecodeGenerator& generator, RegisterID* dst)
805{
806 ArgumentListNode* node = m_args->m_listNode;
807 RefPtr<RegisterID> src = generator.emitNode(node);
808 ASSERT(!node->m_next);
809
810 return generator.moveToDestinationIfNeeded(dst, generator.emitToString(generator.tempDestination(dst), src.get()));
811}
812
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000813// ------------------------------ FunctionCallBracketNode ----------------------------------
814
815RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
816{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000817 bool baseIsSuper = m_base->isSuperNode();
utatane.tea@gmail.comc85b06f2015-05-07 22:35:56 +0000818 bool subscriptIsString = m_subscript->isString();
819
820 RefPtr<RegisterID> base;
821 if (baseIsSuper)
822 base = emitSuperBaseForCallee(generator);
823 else {
824 if (subscriptIsString)
825 base = generator.emitNode(m_base);
826 else
827 base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
828 }
829
830 RefPtr<RegisterID> function;
831 if (subscriptIsString) {
832 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
833 function = generator.emitGetById(generator.tempDestination(dst), base.get(), static_cast<StringNode*>(m_subscript)->value());
834 } else {
835 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
836 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
837 function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
838 }
839
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000840 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000841 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000842 if (baseIsSuper)
843 generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
844 else
845 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000846 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000847 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000848 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000849}
850
851// ------------------------------ FunctionCallDotNode ----------------------------------
852
853RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
854{
855 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000856 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000857 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000858 bool baseIsSuper = m_base->isSuperNode();
859 if (baseIsSuper)
860 generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
861 else
862 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000863 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000864 generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000865 RegisterID* ret = generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000866 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000867 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000868}
869
870RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
871{
872 RefPtr<Label> realCall = generator.newLabel();
873 RefPtr<Label> end = generator.newLabel();
874 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000875 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000876 RefPtr<RegisterID> function;
oliver@apple.comba848d12014-02-12 17:14:23 +0000877 bool emitCallCheck = !generator.isBuiltinFunction();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000878 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000879 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000880 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000881 }
882 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000883 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000884 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
885 RefPtr<RegisterID> profileHookRegister;
886 if (generator.shouldEmitProfileHooks())
887 profileHookRegister = generator.newTemporary();
888 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
889 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000890 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000891 argumentsRegister = generator.emitNode(subject);
892 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
893 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000894 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 +0000895 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000896 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000897 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +0000898
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000899 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
900 CallArguments callArguments(generator, m_args);
901 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000902 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000903 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000904 } else {
905 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
906 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000907 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000908 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000909 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000910 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000911 if (emitCallCheck) {
912 generator.emitJump(end.get());
913 generator.emitLabel(realCall.get());
914 {
915 CallArguments callArguments(generator, m_args);
916 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000917 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000918 }
919 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000920 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +0000921 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000922 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000923}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000924
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000925static bool areTrivialApplyArguments(ArgumentsNode* args)
926{
927 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
928 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
929}
930
931RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
932{
933 // A few simple cases can be trivially handled as ordinary function calls.
934 // function.apply(), function.apply(arg) -> identical to function.call
935 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
936 bool mayBeCall = areTrivialApplyArguments(m_args);
937
938 RefPtr<Label> realCall = generator.newLabel();
939 RefPtr<Label> end = generator.newLabel();
940 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000941 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000942 RefPtr<RegisterID> function;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000943 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000944 bool emitCallCheck = !generator.isBuiltinFunction();
945 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000946 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000947 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
948 }
949 if (mayBeCall) {
950 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
951 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +0000952 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
953 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
954 RefPtr<RegisterID> profileHookRegister;
955 if (generator.shouldEmitProfileHooks())
956 profileHookRegister = generator.newTemporary();
957 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
958 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
959 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
960 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
961
962 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
963 {
964 RefPtr<Label> haveThis = generator.newLabel();
965 RefPtr<Label> end = generator.newLabel();
966 RefPtr<RegisterID> compareResult = generator.newTemporary();
967 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
968 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
969 generator.emitMove(thisRegister.get(), value);
970 generator.emitLoad(index.get(), jsNumber(1));
971 generator.emitJump(end.get());
972 generator.emitLabel(haveThis.get());
973 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
974 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
975 generator.emitMove(argumentsRegister.get(), value);
976 generator.emitLoad(index.get(), jsNumber(2));
977 generator.emitLabel(end.get());
978 };
979 generator.emitEnumeration(this, spread->expression(), extractor);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000980 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 +0000981 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +0000982 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
983 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000984 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 +0000985 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
986 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +0000987 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000988 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000989 } else {
990 m_args->m_listNode = m_args->m_listNode->m_next;
991 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
992 CallArguments callArguments(generator, m_args);
993 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +0000994 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000995 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000996 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000997 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +0000998 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000999 CallArguments callArguments(generator, m_args);
1000 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001001 generator.emitCallInTailPosition(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001002 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001003 } else {
1004 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
1005 RefPtr<RegisterID> profileHookRegister;
1006 if (generator.shouldEmitProfileHooks())
1007 profileHookRegister = generator.newTemporary();
1008 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
1009 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
1010 RefPtr<RegisterID> argsRegister;
1011 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001012 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +00001013
1014 // Function.prototype.apply ignores extra arguments, but we still
1015 // need to evaluate them for side effects.
1016 while ((args = args->m_next))
1017 generator.emitNode(args->m_expr);
1018
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001019 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 +00001020 }
oliver@apple.comba848d12014-02-12 17:14:23 +00001021 if (emitCallCheck) {
1022 generator.emitJump(end.get());
1023 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +00001024 CallArguments callArguments(generator, m_args);
1025 generator.emitMove(callArguments.thisRegister(), base.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001026 generator.emitCallInTailPosition(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +00001027 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001028 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001029 generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +00001030 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001031}
1032
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001033// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001034
ggaren@apple.comf3036112013-04-27 23:14:04 +00001035static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001036{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001037 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001038}
1039
1040static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
1041{
ggaren@apple.comf3036112013-04-27 23:14:04 +00001042 if (dst == srcDst)
1043 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
1044 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
1045 emitIncOrDec(generator, srcDst, oper);
1046 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001047}
1048
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001049RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001050{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001051 if (dst == generator.ignoredResult())
1052 return PrefixNode::emitResolve(generator, dst);
1053
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001054 ASSERT(m_expr->isResolveNode());
1055 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1056 const Identifier& ident = resolve->identifier();
1057
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001058 Variable var = generator.variable(ident);
1059 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001060 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001061 RefPtr<RegisterID> localReg = local;
1062 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001063 generator.emitReadOnlyExceptionIfNeeded(var);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001064 localReg = generator.emitMove(generator.tempDestination(dst), local);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001065 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001066 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
1067 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
1068 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001069 }
oliver@apple.com75f804e2013-03-07 00:25:20 +00001070
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001071 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001072 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1073 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001074 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001075 if (var.isReadOnly()) {
1076 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1077 if (threwException)
1078 return value.get();
1079 }
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001080 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001081 if (!var.isReadOnly()) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001082 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001083 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1084 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001085
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001086 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001087}
1088
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001089RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001090{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001091 if (dst == generator.ignoredResult())
1092 return PrefixNode::emitBracket(generator, dst);
1093
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001094 ASSERT(m_expr->isBracketAccessorNode());
1095 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1096 ExpressionNode* baseNode = bracketAccessor->base();
1097 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001098
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001099 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001100 RefPtr<RegisterID> property = generator.emitNode(subscript);
1101
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001102 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001103 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001104 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001105 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001106 generator.emitPutByVal(base.get(), property.get(), value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001107 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001108 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001109}
1110
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001111RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001112{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +00001113 if (dst == generator.ignoredResult())
1114 return PrefixNode::emitDot(generator, dst);
1115
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001116 ASSERT(m_expr->isDotAccessorNode());
1117 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1118 ExpressionNode* baseNode = dotAccessor->base();
1119 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001120
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001121 RefPtr<RegisterID> base = generator.emitNode(baseNode);
1122
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001123 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001124 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001125 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001126 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001127 generator.emitPutById(base.get(), ident, value.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001128 generator.emitProfileType(value.get(), divotStart(), divotEnd());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +00001129 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001130}
1131
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001132RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001133{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001134 if (m_expr->isResolveNode())
1135 return emitResolve(generator, dst);
1136
1137 if (m_expr->isBracketAccessorNode())
1138 return emitBracket(generator, dst);
1139
1140 if (m_expr->isDotAccessorNode())
1141 return emitDot(generator, dst);
1142
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001143 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001144 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
1145 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001146}
1147
1148// ------------------------------ DeleteResolveNode -----------------------------------
1149
1150RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1151{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001152 Variable var = generator.variable(m_ident);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001153 if (var.local()) {
1154 generator.emitTDZCheckIfNecessary(var, var.local(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001155 return generator.emitLoad(generator.finalDestination(dst), false);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001156 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001157
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001158 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001159 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001160 generator.emitTDZCheckIfNecessary(var, nullptr, base.get());
oliver@apple.com58c86752013-07-25 04:02:40 +00001161 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001162}
1163
1164// ------------------------------ DeleteBracketNode -----------------------------------
1165
1166RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1167{
1168 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001169 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001170
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001171 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001172 if (m_base->isSuperNode())
1173 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001174 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001175}
1176
1177// ------------------------------ DeleteDotNode -----------------------------------
1178
1179RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1180{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001181 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001182
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001183 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001184 if (m_base->isSuperNode())
1185 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001186 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001187}
1188
1189// ------------------------------ DeleteValueNode -----------------------------------
1190
1191RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1192{
1193 generator.emitNode(generator.ignoredResult(), m_expr);
1194
1195 // delete on a non-location expression ignores the value and returns true
1196 return generator.emitLoad(generator.finalDestination(dst), true);
1197}
1198
1199// ------------------------------ VoidNode -------------------------------------
1200
1201RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1202{
1203 if (dst == generator.ignoredResult()) {
1204 generator.emitNode(generator.ignoredResult(), m_expr);
1205 return 0;
1206 }
1207 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1208 return generator.emitLoad(dst, jsUndefined());
1209}
1210
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001211// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001212
1213RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1214{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001215 Variable var = generator.variable(m_ident);
1216 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001217 generator.emitTDZCheckIfNecessary(var, local, nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001218 if (dst == generator.ignoredResult())
1219 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001220 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001221 }
1222
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001223 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1224 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001225 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001226 if (dst == generator.ignoredResult())
1227 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001228 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001229}
1230
1231// ------------------------------ TypeOfValueNode -----------------------------------
1232
1233RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1234{
1235 if (dst == generator.ignoredResult()) {
1236 generator.emitNode(generator.ignoredResult(), m_expr);
1237 return 0;
1238 }
1239 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1240 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1241}
1242
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001243// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001244
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001245RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001246{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001247 ASSERT(m_expr->isResolveNode());
1248 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1249 const Identifier& ident = resolve->identifier();
1250
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001251 Variable var = generator.variable(ident);
1252 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001253 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001254 RefPtr<RegisterID> localReg = local;
1255 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001256 generator.emitReadOnlyExceptionIfNeeded(var);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001257 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001258 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001259 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001260 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001261 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001262 generator.emitMove(localReg.get(), tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001263 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001264 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1265 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001266 emitIncOrDec(generator, localReg.get(), m_operator);
1267 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001268 }
1269
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001270 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001271 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1272 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001273 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001274 if (var.isReadOnly()) {
1275 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1276 if (threwException)
1277 return value.get();
1278 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001279
oliver@apple.com58c86752013-07-25 04:02:40 +00001280 emitIncOrDec(generator, value.get(), m_operator);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001281 if (!var.isReadOnly()) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001282 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound, NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001283 generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
1284 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001285 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001286}
1287
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001288RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001289{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001290 ASSERT(m_expr->isBracketAccessorNode());
1291 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1292 ExpressionNode* baseNode = bracketAccessor->base();
1293 ExpressionNode* subscript = bracketAccessor->subscript();
1294
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001295 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001296 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001297 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1298
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001299 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001300 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001301 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001302 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001303 generator.emitPutByVal(base.get(), property.get(), value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001304 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001305 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1306}
1307
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001308RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001309{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001310 ASSERT(m_expr->isDotAccessorNode());
1311 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1312 ExpressionNode* baseNode = dotAccessor->base();
1313 const Identifier& ident = dotAccessor->identifier();
1314
1315 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001316 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1317
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001318 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001319 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001320 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001321 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001322 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001323 generator.emitProfileType(value, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001324 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1325}
1326
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001327RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001328{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001329 if (m_expr->isResolveNode())
1330 return emitResolve(generator, dst);
1331
1332 if (m_expr->isBracketAccessorNode())
1333 return emitBracket(generator, dst);
1334
1335 if (m_expr->isDotAccessorNode())
1336 return emitDot(generator, dst);
1337
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001338 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001339 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1340 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001341}
1342
1343// ------------------------------ Unary Operation Nodes -----------------------------------
1344
1345RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1346{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001347 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001348 generator.emitExpressionInfo(position(), position(), position());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001349 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001350}
1351
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001352// ------------------------------ BitwiseNotNode -----------------------------------
1353
1354RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1355{
1356 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001357 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1358 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 +00001359}
1360
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001361// ------------------------------ LogicalNotNode -----------------------------------
1362
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001363void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001364{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001365 // reverse the true and false targets
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001366 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001367}
1368
1369
1370// ------------------------------ Binary Operation Nodes -----------------------------------
1371
1372// BinaryOpNode::emitStrcat:
1373//
1374// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1375// more values, where we can determine a set of separate op_add operations would be operating on
1376// string values.
1377//
1378// This function expects to be operating on a graph of AST nodes looking something like this:
1379//
1380// (a)... (b)
1381// \ /
1382// (+) (c)
1383// \ /
1384// [d] ((+))
1385// \ /
1386// [+=]
1387//
1388// The assignment operation is optional, if it exists the register holding the value on the
1389// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1390//
1391// The method should be called on the node at the root of the tree of regular binary add
1392// operations (marked in the diagram with a double set of parentheses). This node must
1393// be performing a string concatenation (determined by statically detecting that at least
1394// one child must be a string).
1395//
1396// Since the minimum number of values being concatenated together is expected to be 3, if
1397// a lhs to a concatenating assignment is not provided then the root add should have at
1398// least one left child that is also an add that can be determined to be operating on strings.
1399//
1400RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1401{
1402 ASSERT(isAdd());
1403 ASSERT(resultDescriptor().definitelyIsString());
1404
1405 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1406 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1407 // added first, and the leftmost child is never added, so the vector produced for the
1408 // example above will be [ c, b ].
1409 Vector<ExpressionNode*, 16> reverseExpressionList;
1410 reverseExpressionList.append(m_expr2);
1411
1412 // Examine the left child of the add. So long as this is a string add, add its right-child
1413 // to the list, and keep processing along the left fork.
1414 ExpressionNode* leftMostAddChild = m_expr1;
1415 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1416 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1417 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1418 }
1419
1420 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1421
1422 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1423 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1424 // op_strcat node handle its conversion if required).
1425 if (lhs)
1426 temporaryRegisters.append(generator.newTemporary());
1427
1428 // Emit code for the leftmost node ((a) in the example).
1429 temporaryRegisters.append(generator.newTemporary());
1430 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1431 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1432
1433 // Note on ordering of conversions:
1434 //
1435 // We maintain the same ordering of conversions as we would see if the concatenations
1436 // was performed as a sequence of adds (otherwise this optimization could change
1437 // behaviour should an object have been provided a valueOf or toString method).
1438 //
1439 // Considering the above example, the sequnce of execution is:
1440 // * evaluate operand (a)
1441 // * evaluate operand (b)
1442 // * convert (a) to primitive <- (this would be triggered by the first add)
1443 // * convert (b) to primitive <- (ditto)
1444 // * evaluate operand (c)
1445 // * convert (c) to primitive <- (this would be triggered by the second add)
1446 // And optionally, if there is an assignment:
1447 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1448 //
1449 // As such we do not plant an op to convert the leftmost child now. Instead, use
1450 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1451 // once the second node has been generated. However, if the leftmost child is an
1452 // immediate we can trivially determine that no conversion will be required.
1453 // If this is the case
1454 if (leftMostAddChild->isString())
1455 leftMostAddChildTempRegister = 0;
1456
1457 while (reverseExpressionList.size()) {
1458 ExpressionNode* node = reverseExpressionList.last();
1459 reverseExpressionList.removeLast();
1460
1461 // Emit the code for the current node.
1462 temporaryRegisters.append(generator.newTemporary());
1463 generator.emitNode(temporaryRegisters.last().get(), node);
1464
1465 // On the first iteration of this loop, when we first reach this point we have just
1466 // generated the second node, which means it is time to convert the leftmost operand.
1467 if (leftMostAddChildTempRegister) {
1468 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1469 leftMostAddChildTempRegister = 0; // Only do this once.
1470 }
1471 // Plant a conversion for this node, if necessary.
1472 if (!node->isString())
1473 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1474 }
1475 ASSERT(temporaryRegisters.size() >= 3);
1476
1477 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1478 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1479 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001480 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001481 // If there is an assignment convert the lhs now. This will also copy lhs to
1482 // the temporary register we allocated for it.
1483 if (lhs)
1484 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1485
1486 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1487}
1488
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001489void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1490{
1491 TriState branchCondition;
1492 ExpressionNode* branchExpression;
1493 tryFoldToBranch(generator, branchCondition, branchExpression);
1494
1495 if (branchCondition == MixedTriState)
1496 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1497 else if (branchCondition == TrueTriState)
1498 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1499 else
1500 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1501}
1502
1503static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1504{
1505 ResultType expressionType = branchExpression->resultDescriptor();
1506
1507 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1508 return true;
1509 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1510 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1511 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1512 return true;
1513
1514 return false;
1515}
1516
1517void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1518{
1519 branchCondition = MixedTriState;
1520 branchExpression = 0;
1521
1522 ConstantNode* constant = 0;
1523 if (m_expr1->isConstant()) {
1524 constant = static_cast<ConstantNode*>(m_expr1);
1525 branchExpression = m_expr2;
1526 } else if (m_expr2->isConstant()) {
1527 constant = static_cast<ConstantNode*>(m_expr2);
1528 branchExpression = m_expr1;
1529 }
1530
1531 if (!constant)
1532 return;
1533 ASSERT(branchExpression);
1534
1535 OpcodeID opcodeID = this->opcodeID();
1536 JSValue value = constant->jsValue(generator);
1537 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1538 if (!canFoldToBranch)
1539 return;
1540
1541 if (opcodeID == op_eq || opcodeID == op_stricteq)
1542 branchCondition = triState(value.pureToBoolean());
1543 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1544 branchCondition = triState(!value.pureToBoolean());
1545}
1546
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001547RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1548{
1549 OpcodeID opcodeID = this->opcodeID();
1550
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001551 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001552 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001553 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001554 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001555
1556 if (opcodeID == op_neq) {
1557 if (m_expr1->isNull() || m_expr2->isNull()) {
1558 RefPtr<RegisterID> src = generator.tempDestination(dst);
1559 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1560 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1561 }
1562 }
1563
oliver@apple.comece74042012-12-01 00:50:39 +00001564 ExpressionNode* left = m_expr1;
1565 ExpressionNode* right = m_expr2;
1566 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1567 if (left->isString())
1568 std::swap(left, right);
1569 }
1570
1571 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001572 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001573 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001574 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001575 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001576 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1577 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001578 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001579 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001580 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001581 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001582 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001583 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1584 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001585 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 +00001586 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1587 return generator.emitUnaryOp(op_unsigned, result, result);
1588 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001589}
1590
1591RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1592{
1593 if (m_expr1->isNull() || m_expr2->isNull()) {
1594 RefPtr<RegisterID> src = generator.tempDestination(dst);
1595 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1596 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1597 }
1598
oliver@apple.comece74042012-12-01 00:50:39 +00001599 ExpressionNode* left = m_expr1;
1600 ExpressionNode* right = m_expr2;
1601 if (left->isString())
1602 std::swap(left, right);
1603
1604 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001605 RefPtr<RegisterID> src2 = generator.emitNode(right);
1606 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001607}
1608
1609RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1610{
oliver@apple.comece74042012-12-01 00:50:39 +00001611 ExpressionNode* left = m_expr1;
1612 ExpressionNode* right = m_expr2;
1613 if (left->isString())
1614 std::swap(left, right);
1615
1616 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001617 RefPtr<RegisterID> src2 = generator.emitNode(right);
1618 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001619}
1620
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001621RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1622{
1623 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001624 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001625 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001626 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 +00001627}
1628
1629RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1630{
1631 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1632 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001633 RefPtr<RegisterID> prototype = generator.newTemporary();
1634 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1635 RefPtr<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001636
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001637 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001638 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001639
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001640 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00001641 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001642
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001643 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com094dbd92012-09-22 01:18:54 +00001644 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001645 generator.emitLabel(target.get());
1646 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001647}
1648
1649// ------------------------------ LogicalOpNode ----------------------------
1650
1651RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1652{
1653 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1654 RefPtr<Label> target = generator.newLabel();
1655
1656 generator.emitNode(temp.get(), m_expr1);
1657 if (m_operator == OpLogicalAnd)
1658 generator.emitJumpIfFalse(temp.get(), target.get());
1659 else
1660 generator.emitJumpIfTrue(temp.get(), target.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001661 generator.emitNodeInTailPosition(temp.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001662 generator.emitLabel(target.get());
1663
1664 return generator.moveToDestinationIfNeeded(dst, temp.get());
1665}
1666
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001667void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001668{
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001669 RefPtr<Label> afterExpr1 = generator.newLabel();
1670 if (m_operator == OpLogicalAnd)
1671 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1672 else
1673 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1674 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001675
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001676 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001677}
1678
1679// ------------------------------ ConditionalNode ------------------------------
1680
1681RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1682{
1683 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1684 RefPtr<Label> beforeElse = generator.newLabel();
1685 RefPtr<Label> afterElse = generator.newLabel();
1686
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001687 RefPtr<Label> beforeThen = generator.newLabel();
1688 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1689 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001690
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001691 generator.emitProfileControlFlow(m_expr1->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001692 generator.emitNodeInTailPosition(newDst.get(), m_expr1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001693 generator.emitJump(afterElse.get());
1694
1695 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001696 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001697 generator.emitNodeInTailPosition(newDst.get(), m_expr2);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001698
1699 generator.emitLabel(afterElse.get());
1700
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001701 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001702
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001703 return newDst.get();
1704}
1705
1706// ------------------------------ ReadModifyResolveNode -----------------------------------
1707
1708// FIXME: should this be moved to be a method on BytecodeGenerator?
1709static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1710{
1711 OpcodeID opcodeID;
1712 switch (oper) {
1713 case OpMultEq:
1714 opcodeID = op_mul;
1715 break;
1716 case OpDivEq:
1717 opcodeID = op_div;
1718 break;
1719 case OpPlusEq:
1720 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1721 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1722 opcodeID = op_add;
1723 break;
1724 case OpMinusEq:
1725 opcodeID = op_sub;
1726 break;
1727 case OpLShift:
1728 opcodeID = op_lshift;
1729 break;
1730 case OpRShift:
1731 opcodeID = op_rshift;
1732 break;
1733 case OpURShift:
1734 opcodeID = op_urshift;
1735 break;
1736 case OpAndEq:
1737 opcodeID = op_bitand;
1738 break;
1739 case OpXOrEq:
1740 opcodeID = op_bitxor;
1741 break;
1742 case OpOrEq:
1743 opcodeID = op_bitor;
1744 break;
1745 case OpModEq:
1746 opcodeID = op_mod;
1747 break;
1748 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001749 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001750 return dst;
1751 }
1752
1753 RegisterID* src2 = generator.emitNode(m_right);
1754
1755 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1756 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1757 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001758 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001759 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1760 if (oper == OpURShift)
1761 return generator.emitUnaryOp(op_unsigned, result, result);
1762 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001763}
1764
1765RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1766{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00001767 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001768 Variable var = generator.variable(m_ident);
1769 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001770 generator.emitTDZCheckIfNecessary(var, local, nullptr);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001771 if (var.isReadOnly()) {
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001772 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001773 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1774 generator.emitProfileType(result, divotStart(), divotEnd());
1775 return result;
ggaren@apple.com6e309822012-09-05 21:44:43 +00001776 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001777
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001778 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001779 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001780 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001781 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001782 generator.emitMove(local, result.get());
1783 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001784 generator.emitProfileType(local, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001785 return generator.moveToDestinationIfNeeded(dst, result.get());
1786 }
1787
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001788 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1789 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001790 generator.emitProfileType(result, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001791 return generator.moveToDestinationIfNeeded(dst, result);
1792 }
1793
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001794 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001795 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1796 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001797 generator.emitTDZCheckIfNecessary(var, value.get(), nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001798 if (var.isReadOnly()) {
1799 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1800 if (threwException)
1801 return value.get();
1802 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001803 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 +00001804 RegisterID* returnResult = result.get();
1805 if (!var.isReadOnly()) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001806 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound, NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001807 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
1808 }
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001809 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001810}
1811
1812// ------------------------------ AssignResolveNode -----------------------------------
1813
1814RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1815{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001816 Variable var = generator.variable(m_ident);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001817 bool isReadOnly = var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001818 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001819 RegisterID* result = nullptr;
1820 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
1821 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001822
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001823 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00001824 result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001825 generator.emitReadOnlyExceptionIfNeeded(var);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001826 generator.emitProfileType(result, var, divotStart(), divotEnd());
1827 } else if (var.isSpecial()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001828 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1829 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001830 generator.emitMove(local, tempDst.get());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001831 generator.emitProfileType(local, var, divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001832 generator.invalidateForInContextForLocal(local);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001833 result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
1834 } else {
1835 RegisterID* right = generator.emitNode(local, m_right);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001836 generator.emitProfileType(right, var, divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001837 generator.invalidateForInContextForLocal(local);
1838 result = generator.moveToDestinationIfNeeded(dst, right);
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001839 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001840
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001841 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001842 generator.liftTDZCheckIfPossible(var);
1843 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001844 }
1845
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001846 if (generator.isStrictMode())
1847 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001848 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001849 if (m_assignmentContext == AssignmentContext::AssignmentExpression)
1850 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001851 if (dst == generator.ignoredResult())
1852 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001853 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001854 if (isReadOnly) {
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00001855 RegisterID* result = generator.emitNode(dst, m_right); // Execute side effects first.
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001856 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
1857 if (threwException)
saambarati1@gmail.com52f68592015-07-28 21:39:34 +00001858 return result;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001859 }
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001860 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001861 RegisterID* returnResult = result.get();
1862 if (!isReadOnly) {
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00001863 returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound,
1864 m_assignmentContext == AssignmentContext::ConstDeclarationStatement || m_assignmentContext == AssignmentContext::DeclarationStatement ? Initialization : NotInitialization);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00001865 generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
1866 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001867
saambarati1@gmail.come4556722015-07-19 16:57:44 +00001868 if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001869 generator.liftTDZCheckIfPossible(var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001870 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001871}
1872
1873// ------------------------------ AssignDotNode -----------------------------------
1874
1875RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1876{
1877 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1878 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001879 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001880 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001881 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001882 generator.emitPutById(base.get(), m_ident, forwardResult);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001883 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001884 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001885}
1886
1887// ------------------------------ ReadModifyDotNode -----------------------------------
1888
1889RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1890{
1891 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1892
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001893 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001894 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001895 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 +00001896
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001897 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001898 RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001899 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001900 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001901}
1902
1903// ------------------------------ AssignErrorNode -----------------------------------
1904
1905RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1906{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001907 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001908}
1909
1910// ------------------------------ AssignBracketNode -----------------------------------
1911
1912RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1913{
1914 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1915 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1916 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001917 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001918
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001919 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001920 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00001921
1922 if (m_subscript->isString())
1923 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
1924 else
1925 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1926
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001927 generator.emitProfileType(forwardResult, divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001928 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001929}
1930
1931// ------------------------------ ReadModifyBracketNode -----------------------------------
1932
1933RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1934{
1935 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1936 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1937
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001938 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001939 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001940 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 +00001941
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001942 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001943 generator.emitPutByVal(base.get(), property.get(), updatedValue);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00001944 generator.emitProfileType(updatedValue, divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001945
1946 return updatedValue;
1947}
1948
1949// ------------------------------ CommaNode ------------------------------------
1950
1951RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1952{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001953 CommaNode* node = this;
1954 for (; node && node->next(); node = node->next())
1955 generator.emitNode(generator.ignoredResult(), node->m_expr);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001956 return generator.emitNodeInTailPosition(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001957}
1958
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001959// ------------------------------ SourceElements -------------------------------
1960
1961
1962inline StatementNode* SourceElements::lastStatement() const
1963{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001964 return m_tail;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001965}
1966
1967inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1968{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001969 for (StatementNode* statement = m_head; statement; statement = statement->next())
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00001970 generator.emitNodeInTailPosition(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001971}
1972
1973// ------------------------------ BlockNode ------------------------------------
1974
1975inline StatementNode* BlockNode::lastStatement() const
1976{
1977 return m_statements ? m_statements->lastStatement() : 0;
1978}
1979
ggaren@apple.comddc6f102015-03-20 20:12:10 +00001980StatementNode* BlockNode::singleStatement() const
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00001981{
1982 return m_statements ? m_statements->singleStatement() : 0;
1983}
1984
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001985void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001986{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001987 if (!m_statements)
1988 return;
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001989 generator.pushLexicalScope(this, true);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001990 m_statements->emitBytecode(generator, dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00001991 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001992}
1993
1994// ------------------------------ EmptyStatementNode ---------------------------
1995
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001996void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001997{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001998 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001999}
2000
2001// ------------------------------ DebuggerStatementNode ---------------------------
2002
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002003void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002004{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002005 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002006}
2007
2008// ------------------------------ ExprStatementNode ----------------------------
2009
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002010void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002011{
2012 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002013 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002014 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002015}
2016
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002017// ------------------------------ DeclarationStatement ----------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002018
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002019void DeclarationStatement::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002020{
2021 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002022 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002023 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002024}
2025
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002026// ------------------------------ EmptyVarExpression ----------------------------
2027
2028RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2029{
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002030 // 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 +00002031 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002032 return nullptr;
2033
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002034 Variable var = generator.variable(m_ident);
2035 if (RegisterID* local = var.local())
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002036 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002037 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002038 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2039 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002040 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00002041 }
2042
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002043 return nullptr;
2044}
2045
2046// ------------------------------ EmptyLetExpression ----------------------------
2047
2048RegisterID* EmptyLetExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2049{
2050 // Lexical declarations like 'let' must move undefined into their variables so we don't
2051 // get TDZ errors for situations like this: `let x; x;`
2052 Variable var = generator.variable(m_ident);
2053 if (RegisterID* local = var.local()) {
2054 generator.emitLoad(local, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002055 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002056 } else {
2057 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
2058 RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002059 generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, Initialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002060 generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002061 }
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002062
2063 // 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 +00002064 return nullptr;
2065}
2066
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002067// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002068
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002069static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002070{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002071 if (statementNode->isBlock())
2072 return static_cast<BlockNode*>(statementNode)->singleStatement();
2073 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00002074}
2075
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002076bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
2077 Label*& trueTarget, FallThroughMode& fallThroughMode)
2078{
2079 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
2080 if (!singleStatement)
2081 return false;
2082
2083 if (singleStatement->isBreak()) {
2084 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
2085 Label* target = breakNode->trivialTarget(generator);
2086 if (!target)
2087 return false;
2088 trueTarget = target;
2089 fallThroughMode = FallThroughMeansFalse;
2090 return true;
2091 }
2092
2093 if (singleStatement->isContinue()) {
2094 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
2095 Label* target = continueNode->trivialTarget(generator);
2096 if (!target)
2097 return false;
2098 trueTarget = target;
2099 fallThroughMode = FallThroughMeansFalse;
2100 return true;
2101 }
2102
2103 return false;
2104}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002105
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002106void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002107{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002108 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00002109
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002110 RefPtr<Label> beforeThen = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002111 RefPtr<Label> beforeElse = generator.newLabel();
2112 RefPtr<Label> afterElse = generator.newLabel();
2113
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002114 Label* trueTarget = beforeThen.get();
2115 Label* falseTarget = beforeElse.get();
2116 FallThroughMode fallThroughMode = FallThroughMeansTrue;
2117 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
2118
2119 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002120 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002121 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002122
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002123 if (!didFoldIfBlock) {
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002124 generator.emitNodeInTailPosition(dst, m_ifBlock);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002125 if (m_elseBlock)
2126 generator.emitJump(afterElse.get());
2127 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002128
2129 generator.emitLabel(beforeElse.get());
2130
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002131 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002132 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002133 generator.emitNodeInTailPosition(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002134 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002135
2136 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002137 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
2138 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002139}
2140
2141// ------------------------------ DoWhileNode ----------------------------------
2142
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002143void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002144{
oliver@apple.com6a976452013-03-11 21:02:39 +00002145 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002146
2147 RefPtr<Label> topOfLoop = generator.newLabel();
2148 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002149 generator.emitLoopHint();
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002150 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002151
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002152 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002153
2154 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002155 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002156 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002157
2158 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002159}
2160
2161// ------------------------------ WhileNode ------------------------------------
2162
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002163void WhileNode::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 RefPtr<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002167
ggaren@apple.com8e8bac42015-03-26 23:35:47 +00002168 generator.emitDebugHook(WillExecuteStatement, m_expr->firstLine(), m_expr->startOffset(), m_expr->lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002169 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002170
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002171 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002172 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002173
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002174 generator.emitProfileControlFlow(m_statement->startOffset());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002175 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002176
2177 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002178 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002179
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002180 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002181
2182 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002183
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002184 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002185}
2186
2187// ------------------------------ ForNode --------------------------------------
2188
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002189void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002190{
oliver@apple.com6a976452013-03-11 21:02:39 +00002191 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002192
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002193 RegisterID* forLoopSymbolTable = nullptr;
2194 generator.pushLexicalScope(this, true, &forLoopSymbolTable);
2195
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002196 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002197
2198 if (m_expr1)
2199 generator.emitNode(generator.ignoredResult(), m_expr1);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002200
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002201 RefPtr<Label> topOfLoop = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002202 if (m_expr2)
2203 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002204
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002205 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002206 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002207 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002208
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002209 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002210
2211 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002212 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002213 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002214 if (m_expr3)
2215 generator.emitNode(generator.ignoredResult(), m_expr3);
2216
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002217 if (m_expr2)
2218 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2219 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002220 generator.emitJump(topOfLoop.get());
2221
2222 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002223 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002224 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002225}
2226
2227// ------------------------------ ForInNode ------------------------------------
2228
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002229RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002230{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002231 if (m_lexpr->isResolveNode()) {
2232 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002233 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002234 }
2235
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002236 if (m_lexpr->isDestructuringNode()) {
2237 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002238 auto binding = assignNode->bindings();
2239 if (!binding->isBindingNode())
2240 return nullptr;
2241
2242 auto simpleBinding = static_cast<BindingNode*>(binding);
2243 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002244 Variable var = generator.variable(ident);
2245 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002246 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002247 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002248 }
2249
2250 return nullptr;
2251}
2252
2253void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2254{
2255 if (m_lexpr->isResolveNode()) {
2256 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002257 Variable var = generator.variable(ident);
2258 if (RegisterID* local = var.local())
2259 generator.emitMove(local, propertyName);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002260 else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002261 if (generator.isStrictMode())
2262 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002263 RegisterID* scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002264 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002265 generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002266 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002267 generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002268 return;
2269 }
2270 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002271 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2272 const Identifier& ident = assignNode->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002273 RegisterID* base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002274 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002275 generator.emitPutById(base, ident, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002276 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002277 return;
2278 }
2279 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002280 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002281 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2282 RegisterID* subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002283 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002284 generator.emitPutByVal(base.get(), subscript, propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002285 generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002286 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002287 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002288
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002289 if (m_lexpr->isDestructuringNode()) {
2290 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002291 auto binding = assignNode->bindings();
2292 if (!binding->isBindingNode()) {
2293 assignNode->bindings()->bindValue(generator, propertyName);
2294 return;
2295 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002296
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002297 auto simpleBinding = static_cast<BindingNode*>(binding);
2298 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002299 Variable var = generator.variable(ident);
2300 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002301 assignNode->bindings()->bindValue(generator, propertyName);
2302 return;
2303 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002304 generator.emitMove(var.local(), propertyName);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002305 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002306 return;
2307 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002308
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002309 RELEASE_ASSERT_NOT_REACHED();
2310}
2311
2312void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
2313{
2314 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002315 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002316 return;
2317 }
2318
2319 RefPtr<Label> end = generator.newLabel();
2320
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002321 RegisterID* forLoopSymbolTable = nullptr;
2322 generator.pushLexicalScope(this, true, &forLoopSymbolTable);
2323
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002324 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002325
2326 RefPtr<RegisterID> base = generator.newTemporary();
2327 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002328 RefPtr<RegisterID> enumerator;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002329 generator.emitNode(base.get(), m_expr);
2330 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002331 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002332
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002333 int profilerStartOffset = m_statement->startOffset();
2334 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002335
2336 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2337
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002338 // Indexed property loop.
2339 {
2340 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2341 RefPtr<Label> loopStart = generator.newLabel();
2342 RefPtr<Label> loopEnd = generator.newLabel();
2343
msaboff@apple.comb644c252015-03-24 10:05:21 +00002344 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002345 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2346 RefPtr<RegisterID> propertyName = generator.newTemporary();
2347
2348 generator.emitLabel(loopStart.get());
2349 generator.emitLoopHint();
2350
2351 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2352 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2353 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
2354 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2355
2356 generator.emitToIndexString(propertyName.get(), i.get());
2357 this->emitLoopHeader(generator, propertyName.get());
2358
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002359 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002360
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002361 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002362 generator.emitNode(dst, m_statement);
2363 generator.popIndexedForInScope(local.get());
2364
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002365 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002366
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002367 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002368 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002369 generator.emitInc(i.get());
2370 generator.emitJump(loopStart.get());
2371
2372 generator.emitLabel(scope->breakTarget());
2373 generator.emitJump(end.get());
2374 generator.emitLabel(loopEnd.get());
2375 }
2376
2377 // Structure property loop.
2378 {
2379 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2380 RefPtr<Label> loopStart = generator.newLabel();
2381 RefPtr<Label> loopEnd = generator.newLabel();
2382
msaboff@apple.comb644c252015-03-24 10:05:21 +00002383 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002384 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002385 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002386
2387 generator.emitLabel(loopStart.get());
2388 generator.emitLoopHint();
2389
2390 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2391 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002392 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002393 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2394
2395 this->emitLoopHeader(generator, propertyName.get());
2396
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002397 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002398
msaboff@apple.comb644c252015-03-24 10:05:21 +00002399 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002400 generator.emitNode(dst, m_statement);
2401 generator.popStructureForInScope(local.get());
2402
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002403 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002404
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002405 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002406 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002407 generator.emitInc(enumeratorIndex.get());
2408 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002409 generator.emitJump(loopStart.get());
2410
2411 generator.emitLabel(scope->breakTarget());
2412 generator.emitJump(end.get());
2413 generator.emitLabel(loopEnd.get());
2414 }
2415
2416 // Generic property loop.
2417 {
2418 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2419 RefPtr<Label> loopStart = generator.newLabel();
2420 RefPtr<Label> loopEnd = generator.newLabel();
2421
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002422 RefPtr<RegisterID> propertyName = generator.newTemporary();
2423
msaboff@apple.comb644c252015-03-24 10:05:21 +00002424 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002425
2426 generator.emitLabel(loopStart.get());
2427 generator.emitLoopHint();
2428
msaboff@apple.comb644c252015-03-24 10:05:21 +00002429 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2430 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2431
2432 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
2433 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2434
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002435 this->emitLoopHeader(generator, propertyName.get());
2436
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002437 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002438
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002439 generator.emitNode(dst, m_statement);
2440
2441 generator.emitLabel(scope->continueTarget());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002442 generator.prepareLexicalScopeForNextForLoopIteration(this, forLoopSymbolTable);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002443 generator.emitInc(enumeratorIndex.get());
2444 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
2445 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002446
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002447 generator.emitLabel(scope->breakTarget());
2448 generator.emitJump(end.get());
2449 generator.emitLabel(loopEnd.get());
2450 }
2451
2452 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2453 generator.emitLabel(end.get());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002454 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002455 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002456}
2457
2458void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2459{
2460 this->emitMultiLoopBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002461}
2462
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002463// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002464void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2465{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002466 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002467 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002468 return;
2469 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002470
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002471 RegisterID* forLoopSymbolTable = nullptr;
2472 generator.pushLexicalScope(this, true, &forLoopSymbolTable);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002473 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002474 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002475 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002476 if (m_lexpr->isResolveNode()) {
2477 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002478 Variable var = generator.variable(ident);
2479 if (RegisterID* local = var.local())
2480 generator.emitMove(local, value);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002481 else {
2482 if (generator.isStrictMode())
2483 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002484 RegisterID* scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002485 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00002486 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002487 }
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002488 generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00002489 } else if (m_lexpr->isDotAccessorNode()) {
2490 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2491 const Identifier& ident = assignNode->identifier();
2492 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2493
2494 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2495 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002496 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002497 } else if (m_lexpr->isBracketAccessorNode()) {
2498 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
2499 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2500 RegisterID* subscript = generator.emitNode(assignNode->subscript());
2501
2502 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2503 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002504 generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002505 } else {
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00002506 ASSERT(m_lexpr->isDestructuringNode());
2507 DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00002508 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002509 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002510 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002511 generator.emitNode(dst, m_statement);
2512 };
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002513 generator.emitEnumeration(this, m_expr, extractor, this, forLoopSymbolTable);
2514 generator.popLexicalScope(this);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002515 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002516}
2517
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002518// ------------------------------ ContinueNode ---------------------------------
2519
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002520Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
2521{
2522 if (generator.shouldEmitDebugHooks())
2523 return 0;
2524
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002525 LabelScopePtr scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002526 ASSERT(scope);
2527
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002528 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002529 return 0;
2530
2531 return scope->continueTarget();
2532}
2533
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002534void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002535{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002536 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002537
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002538 LabelScopePtr scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002539 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002540
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002541 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002542 generator.emitJump(scope->continueTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002543
2544 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002545}
2546
2547// ------------------------------ BreakNode ------------------------------------
2548
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002549Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
2550{
2551 if (generator.shouldEmitDebugHooks())
2552 return 0;
2553
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002554 LabelScopePtr scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002555 ASSERT(scope);
2556
saambarati1@gmail.com3fff23c2015-07-19 00:36:45 +00002557 if (generator.labelScopeDepth() != scope->scopeDepth())
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002558 return 0;
2559
2560 return scope->breakTarget();
2561}
2562
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002563void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002564{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002565 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002566
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002567 LabelScopePtr scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002568 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002569
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002570 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002571 generator.emitJump(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002572
2573 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002574}
2575
2576// ------------------------------ ReturnNode -----------------------------------
2577
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002578void ReturnNode::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());
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002581 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002582
2583 if (dst == generator.ignoredResult())
2584 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002585
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002586 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNodeInTailPosition(dst, m_value) : generator.emitLoad(dst, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002587 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
saambarati1@gmail.com88b7e5b2015-08-05 21:45:20 +00002588 if (generator.isInFinallyBlock()) {
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002589 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002590 generator.emitPopScopes(generator.scopeRegister(), 0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002591 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002592
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002593 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002594 generator.emitReturn(returnRegister.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002595 generator.emitProfileControlFlow(endOffset());
2596 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
2597 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
2598 if (generator.vm()->controlFlowProfiler())
2599 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002600}
2601
2602// ------------------------------ WithNode -------------------------------------
2603
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002604void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002605{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002606 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.com170d6f22012-09-02 21:27:23 +00002607
2608 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002609 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002610 generator.emitPushWithScope(scope.get());
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002611 generator.emitNodeInTailPosition(dst, m_statement);
saambarati1@gmail.come85426c2015-08-07 17:41:22 +00002612 generator.emitPopWithScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002613}
2614
2615// ------------------------------ CaseClauseNode --------------------------------
2616
2617inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2618{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002619 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002620 if (!m_statements)
2621 return;
2622 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002623}
2624
2625// ------------------------------ CaseBlockNode --------------------------------
2626
2627enum SwitchKind {
2628 SwitchUnset = 0,
2629 SwitchNumber = 1,
2630 SwitchString = 2,
2631 SwitchNeither = 3
2632};
2633
2634static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2635{
2636 for (; list; list = list->getNext()) {
2637 ExpressionNode* clauseExpression = list->getClause()->expr();
2638 literalVector.append(clauseExpression);
2639 if (clauseExpression->isNumber()) {
2640 double value = static_cast<NumberNode*>(clauseExpression)->value();
2641 int32_t intVal = static_cast<int32_t>(value);
2642 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
2643 typeForTable = SwitchNeither;
2644 break;
2645 }
2646 if (intVal < min_num)
2647 min_num = intVal;
2648 if (intVal > max_num)
2649 max_num = intVal;
2650 typeForTable = SwitchNumber;
2651 continue;
2652 }
2653 if (clauseExpression->isString()) {
2654 if (typeForTable & ~SwitchString) {
2655 typeForTable = SwitchNeither;
2656 break;
2657 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00002658 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00002659 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00002660 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002661 if (intVal < min_num)
2662 min_num = intVal;
2663 if (intVal > max_num)
2664 max_num = intVal;
2665 }
2666 typeForTable = SwitchString;
2667 continue;
2668 }
2669 typeForTable = SwitchNeither;
2670 break;
2671 }
2672}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002673
2674static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002675{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002676 size_t length = 0;
2677 for (ClauseListNode* node = list1; node; node = node->getNext())
2678 ++length;
2679 for (ClauseListNode* node = list2; node; node = node->getNext())
2680 ++length;
2681 return length;
2682}
2683
2684SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2685{
2686 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
2687 return SwitchInfo::SwitchNone;
2688
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002689 SwitchKind typeForTable = SwitchUnset;
2690 bool singleCharacterSwitch = true;
2691
2692 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2693 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2694
2695 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2696 return SwitchInfo::SwitchNone;
2697
2698 if (typeForTable == SwitchNumber) {
2699 int32_t range = max_num - min_num;
2700 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2701 return SwitchInfo::SwitchImmediate;
2702 return SwitchInfo::SwitchNone;
2703 }
2704
2705 ASSERT(typeForTable == SwitchString);
2706
2707 if (singleCharacterSwitch) {
2708 int32_t range = max_num - min_num;
2709 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2710 return SwitchInfo::SwitchCharacter;
2711 }
2712
2713 return SwitchInfo::SwitchString;
2714}
2715
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002716void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002717{
2718 RefPtr<Label> defaultLabel;
2719 Vector<RefPtr<Label>, 8> labelVector;
2720 Vector<ExpressionNode*, 8> literalVector;
2721 int32_t min_num = std::numeric_limits<int32_t>::max();
2722 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002723 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002724
2725 if (switchType != SwitchInfo::SwitchNone) {
2726 // Prepare the various labels
2727 for (uint32_t i = 0; i < literalVector.size(); i++)
2728 labelVector.append(generator.newLabel());
2729 defaultLabel = generator.newLabel();
2730 generator.beginSwitch(switchExpression, switchType);
2731 } else {
2732 // Setup jumps
2733 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2734 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2735 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2736 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2737 labelVector.append(generator.newLabel());
2738 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2739 }
2740
2741 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2742 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2743 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2744 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2745 labelVector.append(generator.newLabel());
2746 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2747 }
2748 defaultLabel = generator.newLabel();
2749 generator.emitJump(defaultLabel.get());
2750 }
2751
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002752 size_t i = 0;
2753 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2754 generator.emitLabel(labelVector[i++].get());
2755 list->getClause()->emitBytecode(generator, dst);
2756 }
2757
2758 if (m_defaultClause) {
2759 generator.emitLabel(defaultLabel.get());
2760 m_defaultClause->emitBytecode(generator, dst);
2761 }
2762
2763 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2764 generator.emitLabel(labelVector[i++].get());
2765 list->getClause()->emitBytecode(generator, dst);
2766 }
2767 if (!m_defaultClause)
2768 generator.emitLabel(defaultLabel.get());
2769
2770 ASSERT(i == labelVector.size());
2771 if (switchType != SwitchInfo::SwitchNone) {
2772 ASSERT(labelVector.size() == literalVector.size());
2773 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2774 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002775}
2776
2777// ------------------------------ SwitchNode -----------------------------------
2778
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002779void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002780{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002781 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002782
oliver@apple.com6a976452013-03-11 21:02:39 +00002783 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002784
2785 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002786
2787 generator.pushLexicalScope(this, false);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002788 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00002789 generator.popLexicalScope(this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002790
2791 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002792 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002793}
2794
2795// ------------------------------ LabelNode ------------------------------------
2796
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002797void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002798{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002799 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002800
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002801 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002802
oliver@apple.com6a976452013-03-11 21:02:39 +00002803 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
msaboff@apple.comc15ae7e2015-09-16 23:40:35 +00002804 generator.emitNodeInTailPosition(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002805
2806 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002807}
2808
2809// ------------------------------ ThrowNode ------------------------------------
2810
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002811void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002812{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002813 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002814
2815 if (dst == generator.ignoredResult())
2816 dst = 0;
2817 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002818 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002819 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002820
2821 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002822}
2823
2824// ------------------------------ TryNode --------------------------------------
2825
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002826void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002827{
2828 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2829 // optimizer knows they may be jumped to from anywhere.
2830
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002831 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002832
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002833 ASSERT(m_catchBlock || m_finallyBlock);
2834
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002835 RefPtr<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002836 generator.emitLabel(tryStartLabel.get());
2837
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002838 if (m_finallyBlock)
2839 generator.pushFinallyContext(m_finallyBlock);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002840 TryData* tryData = generator.pushTry(tryStartLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002841
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002842 generator.emitNode(dst, m_tryBlock);
2843
2844 if (m_catchBlock) {
2845 RefPtr<Label> catchEndLabel = generator.newLabel();
2846
2847 // Normal path: jump over the catch block.
2848 generator.emitJump(catchEndLabel.get());
2849
2850 // Uncaught exception path: the catch block.
2851 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002852 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
2853 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
2854 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), here.get(), HandlerType::Catch);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002855
2856 if (m_finallyBlock) {
2857 // If the catch block throws an exception and we have a finally block, then the finally
2858 // block should "catch" that exception.
2859 tryData = generator.pushTry(here.get());
2860 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002861
sbarati@apple.com62be0b02015-09-19 15:36:46 +00002862 generator.emitPushCatchScope(m_thrownValueIdent, thrownValueRegister.get(), m_lexicalVariables);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002863 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002864 if (m_finallyBlock)
2865 generator.emitNode(dst, m_catchBlock);
2866 else
2867 generator.emitNodeInTailPosition(dst, m_catchBlock);
sbarati@apple.com62be0b02015-09-19 15:36:46 +00002868 generator.emitPopCatchScope(m_lexicalVariables);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002869 generator.emitLabel(catchEndLabel.get());
2870 }
2871
2872 if (m_finallyBlock) {
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002873 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2874
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002875 generator.popFinallyContext();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002876
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002877 RefPtr<Label> finallyEndLabel = generator.newLabel();
2878
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002879 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002880
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002881 // Normal path: run the finally code, and jump to the end.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002882 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002883 generator.emitNodeInTailPosition(dst, m_finallyBlock);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002884 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002885 generator.emitJump(finallyEndLabel.get());
2886
2887 // Uncaught exception path: invoke the finally block, then re-throw the exception.
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002888 RefPtr<RegisterID> exceptionRegister = generator.newTemporary();
2889 RefPtr<RegisterID> thrownValueRegister = generator.newTemporary();
2890 generator.popTryAndEmitCatch(tryData, exceptionRegister.get(), thrownValueRegister.get(), preFinallyLabel.get(), HandlerType::Finally);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002891 generator.emitProfileControlFlow(finallyStartOffset);
basile_clement@apple.comfb3c1562015-09-04 03:05:46 +00002892 generator.emitNodeInTailPosition(dst, m_finallyBlock);
mark.lam@apple.com6ed08272015-06-05 18:52:12 +00002893 generator.emitThrow(exceptionRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002894
2895 generator.emitLabel(finallyEndLabel.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002896 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002897 } else
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002898 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002899
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002900}
2901
2902// ------------------------------ ScopeNode -----------------------------
2903
2904inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2905{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002906 if (!m_statements)
2907 return;
2908 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002909}
2910
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002911static void emitProgramNodeBytecode(BytecodeGenerator& generator, ScopeNode& scopeNode)
2912{
2913 generator.emitDebugHook(WillExecuteProgram, scopeNode.startLine(), scopeNode.startStartOffset(), scopeNode.startLineStartOffset());
2914
2915 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2916 generator.emitLoad(dstRegister.get(), jsUndefined());
2917 generator.emitProfileControlFlow(scopeNode.startStartOffset());
2918 scopeNode.emitStatementsBytecode(generator, dstRegister.get());
2919
2920 generator.emitDebugHook(DidExecuteProgram, scopeNode.lastLine(), scopeNode.startOffset(), scopeNode.lineStartOffset());
2921 generator.emitEnd(dstRegister.get());
2922}
2923
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002924// ------------------------------ ProgramNode -----------------------------
2925
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002926void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002927{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002928 emitProgramNodeBytecode(generator, *this);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002929}
2930
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00002931// ------------------------------ ModuleProgramNode --------------------
2932
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002933void ModuleProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00002934{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00002935 emitProgramNodeBytecode(generator, *this);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00002936}
2937
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002938// ------------------------------ EvalNode -----------------------------
2939
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002940void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002941{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002942 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002943
2944 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2945 generator.emitLoad(dstRegister.get(), jsUndefined());
2946 emitStatementsBytecode(generator, dstRegister.get());
2947
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002948 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002949 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002950}
2951
ggaren@apple.come7afe402015-08-10 20:24:35 +00002952// ------------------------------ FunctionNode -----------------------------
ggaren@apple.com6f851d72014-12-04 23:47:49 +00002953
2954void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002955{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002956 if (generator.vm()->typeProfiler()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002957 for (size_t i = 0; i < m_parameters->size(); i++) {
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002958 // Destructuring parameters are handled in destructuring nodes.
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00002959 if (!m_parameters->at(i).first->isBindingNode())
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002960 continue;
saambarati1@gmail.com3bde5302015-07-24 18:40:58 +00002961 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002962 RegisterID reg(CallFrame::argumentOffset(i));
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002963 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002964 }
2965 }
2966
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002967 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002968 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002969 emitStatementsBytecode(generator, generator.ignoredResult());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002970
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002971 StatementNode* singleStatement = this->singleStatement();
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002972 ReturnNode* returnNode = 0;
2973
2974 // Check for a return statement at the end of a function composed of a single block.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002975 if (singleStatement && singleStatement->isBlock()) {
2976 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2977 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002978 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002979 }
2980
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002981 // If there is no return we must automatically insert one.
2982 if (!returnNode) {
2983 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00002984 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 +00002985 ASSERT(startOffset() >= lineStartOffset());
2986 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002987 generator.emitReturn(r0);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002988 return;
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002989 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002990}
2991
2992// ------------------------------ FuncDeclNode ---------------------------------
2993
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002994void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002995{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002996}
2997
2998// ------------------------------ FuncExprNode ---------------------------------
2999
3000RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3001{
3002 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
3003}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003004
commit-queue@webkit.orga4201b02015-08-17 22:24:20 +00003005// ------------------------------ ArrowFuncExprNode ---------------------------------
3006
3007RegisterID* ArrowFuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3008{
3009 return generator.emitNewArrowFunctionExpression(generator.finalDestination(dst), this);
3010}
utatane.tea@gmail.comf2fde6a2015-11-02 05:46:17 +00003011
3012// ------------------------------ YieldExprNode --------------------------------
3013
3014RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3015{
3016 // FIXME: This is just a stub. When completing ES6 Generators, we need to implement it.
3017 generator.emitThrowTypeError(ASCIILiteral("Not implemented yet."));
3018 if (dst == generator.ignoredResult())
3019 return 0;
3020 return generator.emitLoad(dst, jsUndefined());
3021}
3022
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003023// ------------------------------ ClassDeclNode ---------------------------------
3024
3025void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3026{
3027 generator.emitNode(dst, m_classDeclaration);
3028}
3029
3030// ------------------------------ ClassExprNode ---------------------------------
3031
3032RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
3033{
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003034 if (!m_name.isNull())
3035 generator.pushLexicalScope(this, true);
3036
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003037 RefPtr<RegisterID> superclass;
3038 if (m_classHeritage) {
3039 superclass = generator.newTemporary();
3040 generator.emitNode(superclass.get(), m_classHeritage);
3041 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003042
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003043 RefPtr<RegisterID> constructor;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003044
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003045 // FIXME: Make the prototype non-configurable & non-writable.
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00003046 if (m_constructorExpression)
3047 constructor = generator.emitNode(dst, m_constructorExpression);
3048 else {
3049 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
3050 m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base, m_name);
3051 }
3052
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003053 const auto& propertyNames = generator.propertyNames();
3054 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003055
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003056 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003057 RefPtr<RegisterID> protoParent = generator.newTemporary();
3058 generator.emitLoad(protoParent.get(), jsNull());
3059
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003060 RefPtr<RegisterID> tempRegister = generator.newTemporary();
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003061
3062 // FIXME: Throw TypeError if it's a generator function.
3063 RefPtr<Label> superclassIsUndefinedLabel = generator.newLabel();
3064 generator.emitJumpIfTrue(generator.emitIsUndefined(tempRegister.get(), superclass.get()), superclassIsUndefinedLabel.get());
3065
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003066 RefPtr<Label> superclassIsNullLabel = generator.newLabel();
3067 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
3068
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003069 RefPtr<Label> superclassIsObjectLabel = generator.newLabel();
3070 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
rniwa@webkit.orgd115b7f2015-05-04 19:23:24 +00003071 generator.emitLabel(superclassIsUndefinedLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003072 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
3073 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003074 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
3075
3076 RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
3077 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
3078 generator.emitThrowTypeError(ASCIILiteral("The superclass's prototype is not an object."));
3079 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
3080
3081 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00003082 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003083 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
3084
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00003085 emitPutHomeObject(generator, constructor.get(), prototype.get());
3086 }
3087
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00003088 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.constructor);
3089 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
3090 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
3091
3092 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.prototype);
3093 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
3094
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003095 if (m_staticMethods)
3096 generator.emitNode(constructor.get(), m_staticMethods);
3097
3098 if (m_instanceMethods)
3099 generator.emitNode(prototype.get(), m_instanceMethods);
3100
utatane.tea@gmail.com0a4a7f82015-10-15 14:35:12 +00003101 if (!m_name.isNull()) {
3102 Variable classNameVar = generator.variable(m_name);
3103 RELEASE_ASSERT(classNameVar.isResolved());
3104 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, classNameVar);
3105 generator.emitPutToScope(scope.get(), classNameVar, constructor.get(), ThrowIfNotFound, Initialization);
3106 generator.popLexicalScope(this);
3107 }
3108
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00003109 return generator.moveToDestinationIfNeeded(dst, constructor.get());
3110}
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003111
3112// ------------------------------ ImportDeclarationNode -----------------------
3113
3114void ImportDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3115{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003116 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003117}
3118
3119// ------------------------------ ExportAllDeclarationNode --------------------
3120
3121void ExportAllDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3122{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003123 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003124}
3125
3126// ------------------------------ ExportDefaultDeclarationNode ----------------
3127
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003128void ExportDefaultDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003129{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003130 ASSERT(m_declaration);
3131 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003132}
3133
3134// ------------------------------ ExportLocalDeclarationNode ------------------
3135
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003136void ExportLocalDeclarationNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003137{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003138 ASSERT(m_declaration);
3139 generator.emitNode(dst, m_declaration);
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003140}
3141
3142// ------------------------------ ExportNamedDeclarationNode ------------------
3143
3144void ExportNamedDeclarationNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3145{
utatane.tea@gmail.coma8309d92015-09-01 02:05:30 +00003146 // Do nothing at runtime.
utatane.tea@gmail.com9f9c9752015-08-04 21:26:49 +00003147}
3148
saambarati1@gmail.comcc3bcb62015-07-02 23:53:10 +00003149// ------------------------------ DestructuringAssignmentNode -----------------
3150RegisterID* DestructuringAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
oliver@apple.comd055db62013-10-02 19:11:04 +00003151{
3152 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
3153 return result;
3154 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
3155 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00003156 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003157 return generator.moveToDestinationIfNeeded(dst, initializer.get());
3158}
3159
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003160static void assignDefaultValueIfUndefined(BytecodeGenerator& generator, RegisterID* maybeUndefined, ExpressionNode* defaultValue)
3161{
3162 ASSERT(defaultValue);
3163 RefPtr<Label> isNotUndefined = generator.newLabel();
3164 generator.emitJumpIfFalse(generator.emitIsUndefined(generator.newTemporary(), maybeUndefined), isNotUndefined.get());
3165 generator.emitNode(maybeUndefined, defaultValue);
3166 generator.emitLabel(isNotUndefined.get());
3167}
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003168
oliver@apple.com47784d62013-10-25 21:31:36 +00003169void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003170{
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003171 RefPtr<RegisterID> iterator = generator.newTemporary();
3172 {
3173 generator.emitGetById(iterator.get(), rhs, generator.propertyNames().iteratorSymbol);
3174 CallArguments args(generator, nullptr);
3175 generator.emitMove(args.thisRegister(), rhs);
3176 generator.emitCall(iterator.get(), iterator.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd());
3177 }
3178
utatane.tea@gmail.coma5c94332015-06-23 00:51:44 +00003179 if (m_targetPatterns.isEmpty()) {
3180 generator.emitIteratorClose(iterator.get(), this);
3181 return;
3182 }
3183
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003184 RefPtr<RegisterID> done;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003185 for (auto& target : m_targetPatterns) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003186 switch (target.bindingType) {
3187 case BindingType::Elision:
3188 case BindingType::Element: {
3189 RefPtr<Label> iterationSkipped = generator.newLabel();
3190 if (!done)
3191 done = generator.newTemporary();
3192 else
3193 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003194
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003195 RefPtr<RegisterID> value = generator.newTemporary();
3196 generator.emitIteratorNext(value.get(), iterator.get(), this);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003197 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003198 generator.emitJumpIfTrue(done.get(), iterationSkipped.get());
3199 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003200
3201 {
3202 RefPtr<Label> valueIsSet = generator.newLabel();
3203 generator.emitJump(valueIsSet.get());
3204 generator.emitLabel(iterationSkipped.get());
3205 generator.emitLoad(value.get(), jsUndefined());
3206 generator.emitLabel(valueIsSet.get());
3207 }
3208
3209 if (target.bindingType == BindingType::Element) {
3210 if (target.defaultValue)
3211 assignDefaultValueIfUndefined(generator, value.get(), target.defaultValue);
3212 target.pattern->bindValue(generator, value.get());
3213 }
3214 break;
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003215 }
3216
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003217 case BindingType::RestElement: {
3218 RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
3219
3220 RefPtr<Label> iterationDone = generator.newLabel();
3221 if (!done)
3222 done = generator.newTemporary();
3223 else
3224 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3225
3226 RefPtr<RegisterID> index = generator.newTemporary();
3227 generator.emitLoad(index.get(), jsNumber(0));
3228 RefPtr<Label> loopStart = generator.newLabel();
3229 generator.emitLabel(loopStart.get());
3230
3231 RefPtr<RegisterID> value = generator.newTemporary();
3232 generator.emitIteratorNext(value.get(), iterator.get(), this);
3233 generator.emitGetById(done.get(), value.get(), generator.propertyNames().done);
3234 generator.emitJumpIfTrue(done.get(), iterationDone.get());
3235 generator.emitGetById(value.get(), value.get(), generator.propertyNames().value);
3236
3237 generator.emitDirectPutByVal(array.get(), index.get(), value.get());
3238 generator.emitInc(index.get());
3239 generator.emitJump(loopStart.get());
3240
3241 generator.emitLabel(iterationDone.get());
3242 target.pattern->bindValue(generator, array.get());
3243 break;
3244 }
3245 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003246 }
utatane.tea@gmail.com5210f302015-06-20 11:04:27 +00003247
3248 RefPtr<Label> iteratorClosed = generator.newLabel();
3249 generator.emitJumpIfTrue(done.get(), iteratorClosed.get());
3250 generator.emitIteratorClose(iterator.get(), this);
3251 generator.emitLabel(iteratorClosed.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003252}
3253
3254RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
3255{
oliver@apple.comd055db62013-10-02 19:11:04 +00003256 if (!rhs->isSimpleArray())
3257 return 0;
oliver@apple.com47784d62013-10-25 21:31:36 +00003258
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003259 RefPtr<RegisterID> resultRegister;
3260 if (dst && dst != generator.ignoredResult())
3261 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00003262 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
3263 Vector<ExpressionNode*> elements;
3264 for (; elementNodes; elementNodes = elementNodes->next())
3265 elements.append(elementNodes->value());
3266 if (m_targetPatterns.size() != elements.size())
3267 return 0;
3268 Vector<RefPtr<RegisterID>> registers;
3269 registers.reserveCapacity(m_targetPatterns.size());
3270 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3271 registers.uncheckedAppend(generator.newTemporary());
3272 generator.emitNode(registers.last().get(), elements[i]);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003273 if (m_targetPatterns[i].defaultValue)
3274 assignDefaultValueIfUndefined(generator, registers.last().get(), m_targetPatterns[i].defaultValue);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003275 if (resultRegister)
3276 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003277 }
3278
3279 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003280 if (m_targetPatterns[i].pattern)
3281 m_targetPatterns[i].pattern->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003282 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003283 if (resultRegister)
3284 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00003285 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00003286}
3287
3288void ArrayPatternNode::toString(StringBuilder& builder) const
3289{
3290 builder.append('[');
3291 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003292 const auto& target = m_targetPatterns[i];
3293
3294 switch (target.bindingType) {
3295 case BindingType::Elision:
oliver@apple.comd055db62013-10-02 19:11:04 +00003296 builder.append(',');
utatane.tea@gmail.com412d7612015-06-26 03:13:25 +00003297 break;
3298
3299 case BindingType::Element:
3300 target.pattern->toString(builder);
3301 if (i < m_targetPatterns.size() - 1)
3302 builder.append(',');
3303 break;
3304
3305 case BindingType::RestElement:
3306 builder.append("...");
3307 target.pattern->toString(builder);
3308 break;
oliver@apple.comd055db62013-10-02 19:11:04 +00003309 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003310 }
3311 builder.append(']');
3312}
3313
3314void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3315{
3316 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
saambarati1@gmail.comc497d152015-07-17 18:48:30 +00003317 if (DestructuringPatternNode* node = m_targetPatterns[i].pattern)
oliver@apple.comd055db62013-10-02 19:11:04 +00003318 node->collectBoundIdentifiers(identifiers);
3319 }
3320}
3321
3322void ObjectPatternNode::toString(StringBuilder& builder) const
3323{
3324 builder.append('{');
3325 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003326 if (m_targetPatterns[i].wasString)
akling@apple.coma9904fb2015-05-08 08:44:23 +00003327 builder.appendQuotedJSONString(m_targetPatterns[i].propertyName.string());
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003328 else
oliver@apple.comd055db62013-10-02 19:11:04 +00003329 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00003330 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00003331 m_targetPatterns[i].pattern->toString(builder);
3332 if (i < m_targetPatterns.size() - 1)
3333 builder.append(',');
3334 }
3335 builder.append('}');
3336}
3337
oliver@apple.com47784d62013-10-25 21:31:36 +00003338void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003339{
3340 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3341 auto& target = m_targetPatterns[i];
3342 RefPtr<RegisterID> temp = generator.newTemporary();
3343 generator.emitGetById(temp.get(), rhs, target.propertyName);
saambarati1@gmail.com174581a2015-06-18 12:35:32 +00003344 if (target.defaultValue)
3345 assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
oliver@apple.com47784d62013-10-25 21:31:36 +00003346 target.pattern->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003347 }
3348}
3349
3350void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3351{
3352 for (size_t i = 0; i < m_targetPatterns.size(); i++)
3353 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
3354}
3355
oliver@apple.com47784d62013-10-25 21:31:36 +00003356void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003357{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003358 Variable var = generator.variable(m_boundProperty);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003359 bool isReadOnly = var.isReadOnly() && m_bindingContext != AssignmentContext::ConstDeclarationStatement;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003360 if (RegisterID* local = var.local()) {
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003361 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3362 generator.emitTDZCheckIfNecessary(var, local, nullptr);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003363 if (isReadOnly) {
3364 generator.emitReadOnlyExceptionIfNeeded(var);
3365 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00003366 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003367 generator.emitMove(local, value);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003368 generator.emitProfileType(local, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003369 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003370 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003371 return;
3372 }
3373 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003374 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003375 RegisterID* scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003376 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003377 if (m_bindingContext == AssignmentContext::AssignmentExpression)
3378 generator.emitTDZCheckIfNecessary(var, nullptr, scope);
saambarati1@gmail.com6541a1e2015-08-25 18:40:14 +00003379 if (isReadOnly) {
3380 generator.emitReadOnlyExceptionIfNeeded(var);
3381 return;
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003382 }
saambarati1@gmail.com060e7512015-09-03 19:45:44 +00003383 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound,
3384 m_bindingContext == AssignmentContext::ConstDeclarationStatement || m_bindingContext == AssignmentContext::DeclarationStatement ? Initialization : NotInitialization);
saambarati1@gmail.comf07b1bc2015-07-28 22:39:12 +00003385 generator.emitProfileType(value, var, divotStart(), divotEnd());
saambarati1@gmail.come4556722015-07-19 16:57:44 +00003386 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
saambarati1@gmail.com144f17c2015-07-15 21:41:08 +00003387 generator.liftTDZCheckIfPossible(var);
oliver@apple.comd055db62013-10-02 19:11:04 +00003388 return;
3389}
3390
3391void BindingNode::toString(StringBuilder& builder) const
3392{
3393 builder.append(m_boundProperty.string());
3394}
3395
3396void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3397{
3398 identifiers.append(m_boundProperty);
3399}
commit-queue@webkit.org88a74762015-11-19 22:54:46 +00003400
3401void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
3402{
3403}
3404
3405void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
3406{
3407 if (m_assignmentTarget->isResolveNode()) {
3408 ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
3409 Variable var = generator.variable(lhs->identifier());
3410 bool isReadOnly = var.isReadOnly();
3411 if (RegisterID* local = var.local()) {
3412 generator.emitTDZCheckIfNecessary(var, local, nullptr);
3413
3414 if (isReadOnly)
3415 generator.emitReadOnlyExceptionIfNeeded(var);
3416 else {
3417 generator.invalidateForInContextForLocal(local);
3418 generator.moveToDestinationIfNeeded(local, value);
3419 generator.emitProfileType(local, divotStart(), divotEnd());
3420 }
3421 return;
3422 }
3423 if (generator.isStrictMode())
3424 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3425 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
3426 generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
3427 if (isReadOnly) {
3428 bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
3429 if (threwException)
3430 return;
3431 }
3432 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3433 if (!isReadOnly) {
3434 generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
3435 generator.emitProfileType(value, var, divotStart(), divotEnd());
3436 }
3437 } else if (m_assignmentTarget->isDotAccessorNode()) {
3438 DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
3439 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
3440 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3441 generator.emitPutById(base.get(), lhs->identifier(), value);
3442 generator.emitProfileType(value, divotStart(), divotEnd());
3443 } else if (m_assignmentTarget->isBracketAccessorNode()) {
3444 BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
3445 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
3446 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(lhs->subscript(), true, false);
3447 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
3448 generator.emitPutByVal(base.get(), property.get(), value);
3449 generator.emitProfileType(value, divotStart(), divotEnd());
3450 }
3451}
3452
3453void AssignmentElementNode::toString(StringBuilder& builder) const
3454{
3455 if (m_assignmentTarget->isResolveNode())
3456 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
3457}
3458
sbarati@apple.comc0722da2015-11-20 02:37:47 +00003459void RestParameterNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3460{
3461 identifiers.append(m_name);
3462}
3463void RestParameterNode::toString(StringBuilder& builder) const
3464{
3465 builder.append(m_name.string());
3466}
3467void RestParameterNode::bindValue(BytecodeGenerator&, RegisterID*) const
3468{
3469 RELEASE_ASSERT_NOT_REACHED();
3470}
3471void RestParameterNode::emit(BytecodeGenerator& generator)
3472{
3473 Variable var = generator.variable(m_name);
3474 if (RegisterID* local = var.local()) {
3475 generator.emitRestParameter(local, m_numParametersToSkip);
3476 generator.emitProfileType(local, var, m_divotStart, m_divotEnd);
3477 return;
3478 }
3479
3480 RefPtr<RegisterID> restParameterArray = generator.emitRestParameter(generator.newTemporary(), m_numParametersToSkip);
3481 generator.emitProfileType(restParameterArray.get(), var, m_divotStart, m_divotEnd);
3482 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
3483 generator.emitExpressionInfo(m_divotEnd, m_divotStart, m_divotEnd);
3484 generator.emitPutToScope(scope.get(), var, restParameterArray.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, Initialization);
3485}
3486
3487
oliver@apple.com72f8a822013-10-17 01:02:34 +00003488RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3489{
3490 RELEASE_ASSERT_NOT_REACHED();
3491 return 0;
3492}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003493
3494} // namespace JSC