blob: a936d70d7ab089b814e5ffc3d32e9d0a28d4ec68 [file] [log] [blame]
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
mark.lam@apple.comfaa53932013-03-20 09:09:38 +00004* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 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"
ggaren@apple.comce2b6672012-08-28 17:52:18 +000038#include "JSNameScope.h"
oliver@apple.comd055db62013-10-02 19:11:04 +000039#include "JSONObject.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000040#include "LabelScope.h"
41#include "Lexer.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000042#include "JSCInlines.h"
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"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000049#include <wtf/Assertions.h>
50#include <wtf/RefCountedLeakCounter.h>
51#include <wtf/Threading.h>
52
53using namespace WTF;
54
55namespace JSC {
56
57/*
58 Details of the emitBytecode function.
59
60 Return value: The register holding the production's value.
61 dst: An optional parameter specifying the most efficient destination at
62 which to store the production's value. The callee must honor dst.
63
64 The dst argument provides for a crude form of copy propagation. For example,
65
66 x = 1
67
68 becomes
69
70 load r[x], 1
71
72 instead of
73
74 load r0, 1
75 mov r[x], r0
76
77 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
78*/
79
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +000080void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
81{
82 RegisterID* result = generator.emitNode(this);
83 if (fallThroughMode == FallThroughMeansTrue)
84 generator.emitJumpIfFalse(result, falseTarget);
85 else
86 generator.emitJumpIfTrue(result, trueTarget);
87}
88
mjs@apple.comaed3cef2009-12-09 01:29:52 +000089// ------------------------------ ThrowableExpressionData --------------------------------
90
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000091RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000092{
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +000093 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com4920ae92010-11-12 03:06:07 +000094 generator.emitThrowReferenceError(message);
95 return generator.newTemporary();
mjs@apple.comaed3cef2009-12-09 01:29:52 +000096}
97
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000098// ------------------------------ ConstantNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +000099
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000100void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000101{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000102 TriState value = jsValue(generator).pureToBoolean();
103 if (value == MixedTriState)
104 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
105 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
106 generator.emitJump(trueTarget);
107 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
108 generator.emitJump(falseTarget);
109
110 // All other cases are unconditional fall-throughs, like "if (true)".
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000111}
112
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000113RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000114{
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000115 if (dst == generator.ignoredResult())
116 return 0;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000117 return generator.emitLoad(dst, jsValue(generator));
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000118}
119
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000120JSValue StringNode::jsValue(BytecodeGenerator& generator) const
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000121{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000122 return generator.addStringConstant(m_value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000123}
124
125// ------------------------------ RegExpNode -----------------------------------
126
127RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
128{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000129 if (dst == generator.ignoredResult())
130 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000131 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 +0000132}
133
134// ------------------------------ ThisNode -------------------------------------
135
136RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
137{
138 if (dst == generator.ignoredResult())
139 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000140
141 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000142 if (generator.vm()->typeProfiler()) {
143 generator.emitProfileType(generator.thisRegister(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000144 static const unsigned thisLength = 4;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000145 generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000146 }
147 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000148}
149
150// ------------------------------ ResolveNode ----------------------------------
151
152bool ResolveNode::isPure(BytecodeGenerator& generator) const
153{
oliver@apple.com58c86752013-07-25 04:02:40 +0000154 return generator.local(m_ident).get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000155}
156
157RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
158{
oliver@apple.com58c86752013-07-25 04:02:40 +0000159 if (Local local = generator.local(m_ident)) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000160 if (dst == generator.ignoredResult())
161 return 0;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000162 if (generator.vm()->typeProfiler()) {
163 generator.emitProfileType(local.get(), ProfileTypeBytecodeHasGlobalID, nullptr);
164 generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000165 }
oliver@apple.com58c86752013-07-25 04:02:40 +0000166 return generator.moveToDestinationIfNeeded(dst, local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000167 }
168
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000169 JSTextPosition divot = m_start + m_ident.length();
170 generator.emitExpressionInfo(divot, m_start, divot);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000171 ResolveScopeInfo resolveScopeInfo;
172 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000173 RegisterID* finalDest = generator.finalDestination(dst);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000174 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000175 if (generator.vm()->typeProfiler()) {
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000176 generator.emitProfileType(finalDest, resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000177 generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000178 }
179 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000180}
181
182// ------------------------------ ArrayNode ------------------------------------
183
184RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
185{
186 // FIXME: Should we put all of this code into emitNewArray?
187
188 unsigned length = 0;
189 ElementNode* firstPutElement;
190 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000191 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000192 break;
193 ++length;
194 }
195
196 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000197 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000198
oliver@apple.coma991d692011-06-14 23:39:25 +0000199 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000200 ElementNode* n = firstPutElement;
201 for (; n; n = n->next()) {
202 if (n->value()->isSpreadExpression())
203 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000204 RegisterID* value = generator.emitNode(n->value());
205 length += n->elision();
206 generator.emitPutByIndex(array.get(), length++, value);
207 }
208
209 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000210 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000211 generator.emitPutById(array.get(), generator.propertyNames().length, value);
212 }
213
214 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000215
216handleSpread:
217 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
218 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
219 {
oliver@apple.come050d642013-10-19 00:09:28 +0000220 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000221 generator.emitInc(index.get());
222 };
223 for (; n; n = n->next()) {
224 if (n->elision())
225 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
226 if (n->value()->isSpreadExpression()) {
227 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
228 generator.emitEnumeration(spread, spread->expression(), spreader);
229 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000230 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000231 generator.emitInc(index.get());
232 }
233 }
234
235 if (m_elision) {
236 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
237 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
238 }
239 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000240}
241
242bool ArrayNode::isSimpleArray() const
243{
244 if (m_elision || m_optional)
245 return false;
246 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
247 if (ptr->elision())
248 return false;
249 }
250 return true;
251}
252
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000253ArgumentListNode* ArrayNode::toArgumentList(VM* vm, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000254{
255 ASSERT(!m_elision && !m_optional);
256 ElementNode* ptr = m_element;
257 if (!ptr)
258 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000259 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000260 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000261 location.startOffset = startPosition;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000262 ArgumentListNode* head = new (vm) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000263 ArgumentListNode* tail = head;
264 ptr = ptr->next();
265 for (; ptr; ptr = ptr->next()) {
266 ASSERT(!ptr->elision());
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000267 tail = new (vm) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000268 }
269 return head;
270}
271
272// ------------------------------ ObjectLiteralNode ----------------------------
273
274RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
275{
276 if (!m_list) {
277 if (dst == generator.ignoredResult())
278 return 0;
279 return generator.emitNewObject(generator.finalDestination(dst));
280 }
281 return generator.emitNode(dst, m_list);
282}
283
284// ------------------------------ PropertyListNode -----------------------------
285
286RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
287{
288 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
289
290 generator.emitNewObject(newObj.get());
291
barraclough@apple.com09a55682012-01-30 18:28:39 +0000292 // Fast case: this loop just handles regular value properties.
293 PropertyListNode* p = this;
oliver@apple.com72d38322013-10-21 19:23:24 +0000294 for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next) {
295 if (p->m_node->m_name) {
296 generator.emitDirectPutById(newObj.get(), *p->m_node->name(), generator.emitNode(p->m_node->m_assign));
297 continue;
298 }
299 RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression);
300 generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign));
301 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000302
303 // Were there any get/set properties?
304 if (p) {
305 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
306 typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
307 GetterSetterMap map;
308
309 // Build a map, pairing get/set values together.
310 for (PropertyListNode* q = p; q; q = q->m_next) {
311 PropertyNode* node = q->m_node;
312 if (node->m_type == PropertyNode::Constant)
313 continue;
314
paroga@webkit.orgf990c252012-02-20 23:37:01 +0000315 GetterSetterPair pair(node, static_cast<PropertyNode*>(0));
oliver@apple.com72d38322013-10-21 19:23:24 +0000316 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +0000317 if (!result.isNewEntry)
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000318 result.iterator->value.second = node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000319 }
320
321 // Iterate over the remaining properties in the list.
322 for (; p; p = p->m_next) {
323 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000324
325 // Handle regular values.
326 if (node->m_type == PropertyNode::Constant) {
oliver@apple.com72d38322013-10-21 19:23:24 +0000327 if (node->name()) {
328 generator.emitDirectPutById(newObj.get(), *node->name(), generator.emitNode(node->m_assign));
329 continue;
330 }
331 RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression);
332 generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign));
barraclough@apple.com09a55682012-01-30 18:28:39 +0000333 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000334 }
oliver@apple.com72d38322013-10-21 19:23:24 +0000335
336 RegisterID* value = generator.emitNode(node->m_assign);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000337
338 // This is a get/set property, find its entry in the map.
339 ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
oliver@apple.com72d38322013-10-21 19:23:24 +0000340 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000341 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000342 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000343
344 // Was this already generated as a part of its partner?
345 if (pair.second == node)
346 continue;
347
348 // Generate the paired node now.
349 RefPtr<RegisterID> getterReg;
350 RefPtr<RegisterID> setterReg;
351
352 if (node->m_type == PropertyNode::Getter) {
353 getterReg = value;
354 if (pair.second) {
355 ASSERT(pair.second->m_type == PropertyNode::Setter);
356 setterReg = generator.emitNode(pair.second->m_assign);
357 } else {
358 setterReg = generator.newTemporary();
359 generator.emitLoad(setterReg.get(), jsUndefined());
360 }
361 } else {
362 ASSERT(node->m_type == PropertyNode::Setter);
363 setterReg = value;
364 if (pair.second) {
365 ASSERT(pair.second->m_type == PropertyNode::Getter);
366 getterReg = generator.emitNode(pair.second->m_assign);
367 } else {
368 getterReg = generator.newTemporary();
369 generator.emitLoad(getterReg.get(), jsUndefined());
370 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000371 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000372
oliver@apple.com72d38322013-10-21 19:23:24 +0000373 generator.emitPutGetterSetter(newObj.get(), *node->name(), getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000374 }
375 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000376
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000377 return generator.moveToDestinationIfNeeded(dst, newObj.get());
378}
379
380// ------------------------------ BracketAccessorNode --------------------------------
381
382RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
383{
ggaren@apple.com13e02b92012-09-20 19:51:58 +0000384 if (m_base->isResolveNode()
385 && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())
386 && !generator.symbolTable().slowArguments()) {
oliver@apple.com74e00b02010-09-25 21:42:00 +0000387 RegisterID* property = generator.emitNode(m_subscript);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000388 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com71684cb2014-10-17 16:07:08 +0000389 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedLocalArgumentsRegister(), property);
oliver@apple.com74e00b02010-09-25 21:42:00 +0000390 }
391
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000392 RegisterID* ret;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000393 RegisterID* finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000394
395 if (m_subscript->isString()) {
396 RefPtr<RegisterID> base = generator.emitNode(m_base);
397 ret = generator.emitGetById(finalDest, base.get(), static_cast<StringNode*>(m_subscript)->value());
398 } else {
399 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
400 RegisterID* property = generator.emitNode(m_subscript);
401 ret = generator.emitGetByVal(finalDest, base.get(), property);
402 }
403
404 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
405
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000406 if (generator.vm()->typeProfiler()) {
407 generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
408 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000409 }
410 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000411}
412
413// ------------------------------ DotAccessorNode --------------------------------
414
415RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
416{
oliver@apple.com74e00b02010-09-25 21:42:00 +0000417 if (m_ident == generator.propertyNames().length) {
418 if (!m_base->isResolveNode())
419 goto nonArgumentsPath;
420 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
421 if (!generator.willResolveToArguments(resolveNode->identifier()))
422 goto nonArgumentsPath;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000423 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com71684cb2014-10-17 16:07:08 +0000424 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedLocalArgumentsRegister());
oliver@apple.com74e00b02010-09-25 21:42:00 +0000425 }
426
427nonArgumentsPath:
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000428 RegisterID* base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000429 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000430 RegisterID* finalDest = generator.finalDestination(dst);
431 RegisterID* ret = generator.emitGetById(finalDest, base, m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000432 if (generator.vm()->typeProfiler()) {
433 generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
434 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000435 }
436 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000437}
438
439// ------------------------------ ArgumentListNode -----------------------------
440
441RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
442{
443 ASSERT(m_expr);
444 return generator.emitNode(dst, m_expr);
445}
446
447// ------------------------------ NewExprNode ----------------------------------
448
449RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
450{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000451 ExpectedFunction expectedFunction;
452 if (m_expr->isResolveNode())
453 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
454 else
455 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000456 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000457 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000458 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000459 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000460}
461
oliver@apple.com72f8a822013-10-17 01:02:34 +0000462CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000463 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000464 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000465{
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +0000466 if (generator.shouldEmitProfileHooks())
467 m_profileHookRegister = generator.newTemporary();
ggaren@apple.com50c5ac22011-11-14 23:16:27 +0000468
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000469 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000470 if (argumentsNode) {
471 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
472 ++argumentCountIncludingThis;
473 }
474
475 m_argv.grow(argumentCountIncludingThis);
476 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
477 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000478 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 +0000479 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000480
481 while (stackOffset() % stackAlignmentRegisters()) {
482 m_argv.insert(0, generator.newTemporary());
483 m_padding++;
484 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000485}
486
487// ------------------------------ EvalFunctionCallNode ----------------------------------
488
489RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
490{
oliver@apple.com58c86752013-07-25 04:02:40 +0000491 if (Local local = generator.local(generator.propertyNames().eval)) {
492 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
493 CallArguments callArguments(generator, m_args);
494 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000495 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000496 }
497
498 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000499 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000500 JSTextPosition newDivot = divotStart() + 4;
501 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000502 ResolveScopeInfo resolveScopeInfo;
503 generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval, resolveScopeInfo);
504 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound, resolveScopeInfo);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000505 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000506}
507
508// ------------------------------ FunctionCallValueNode ----------------------------------
509
510RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
511{
512 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000513 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000514 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000515 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000516 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000517 if (generator.vm()->typeProfiler()) {
518 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
519 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000520 }
521 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000522}
523
524// ------------------------------ FunctionCallResolveNode ----------------------------------
525
526RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
527{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000528 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000529
oliver@apple.com58c86752013-07-25 04:02:40 +0000530 if (Local local = generator.local(m_ident)) {
531 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000532 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000533 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000534 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000535 // This passes NoExpectedFunction because we expect that if the function is in a
536 // local variable, then it's not one of our built-in constructors.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000537 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000538 if (generator.vm()->typeProfiler()) {
539 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
540 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000541 }
542 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000543 }
544
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000545 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000546 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000547 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000548
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000549 JSTextPosition newDivot = divotStart() + m_ident.length();
550 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000551 ResolveScopeInfo resolveScopeInfo;
552 generator.emitResolveScope(callArguments.thisRegister(), m_ident, resolveScopeInfo);
553 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound, resolveScopeInfo);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000554 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000555 if (generator.vm()->typeProfiler()) {
556 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
557 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000558 }
559 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000560}
561
562// ------------------------------ FunctionCallBracketNode ----------------------------------
563
564RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
565{
566 RefPtr<RegisterID> base = generator.emitNode(m_base);
567 RegisterID* property = generator.emitNode(m_subscript);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000568 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000569 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000570 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000571 CallArguments callArguments(generator, m_args);
572 generator.emitMove(callArguments.thisRegister(), base.get());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000573 RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000574 if (generator.vm()->typeProfiler()) {
575 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
576 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000577 }
578 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000579}
580
581// ------------------------------ FunctionCallDotNode ----------------------------------
582
583RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
584{
585 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000586 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000587 CallArguments callArguments(generator, m_args);
588 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000589 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000590 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000591 RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000592 if (generator.vm()->typeProfiler()) {
593 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
594 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000595 }
596 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000597}
598
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000599static RegisterID* getArgumentByVal(BytecodeGenerator& generator, ExpressionNode* base, RegisterID* property, RegisterID* dst, JSTextPosition divot, JSTextPosition divotStart, JSTextPosition divotEnd)
600{
601 if (base->isResolveNode()
602 && generator.willResolveToArguments(static_cast<ResolveNode*>(base)->identifier())
603 && !generator.symbolTable().slowArguments()) {
604 generator.emitExpressionInfo(divot, divotStart, divotEnd);
oliver@apple.com71684cb2014-10-17 16:07:08 +0000605 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedLocalArgumentsRegister(), property);
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000606 }
607 return nullptr;
608}
609
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000610RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
611{
612 RefPtr<Label> realCall = generator.newLabel();
613 RefPtr<Label> end = generator.newLabel();
614 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000615 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000616 RefPtr<RegisterID> function;
oliver@apple.comba848d12014-02-12 17:14:23 +0000617 bool emitCallCheck = !generator.isBuiltinFunction();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000618 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000619 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000620 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000621 }
622 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000623 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000624 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
625 RefPtr<RegisterID> profileHookRegister;
626 if (generator.shouldEmitProfileHooks())
627 profileHookRegister = generator.newTemporary();
628 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
629 ExpressionNode* subject = spread->expression();
630 RefPtr<RegisterID> thisRegister = getArgumentByVal(generator, subject, generator.emitLoad(0, jsNumber(0)), 0, spread->divot(), spread->divotStart(), spread->divotEnd());
631 RefPtr<RegisterID> argumentsRegister;
632 if (thisRegister)
oliver@apple.com71684cb2014-10-17 16:07:08 +0000633 argumentsRegister = generator.uncheckedLocalArgumentsRegister();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000634 else {
635 argumentsRegister = generator.emitNode(subject);
636 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
637 thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
638 }
639 generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
640 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000641 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000642 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +0000643
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000644 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
645 CallArguments callArguments(generator, m_args);
646 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000647 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000648 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000649 } else {
650 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
651 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000652 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000653 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000654 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000655 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000656 if (emitCallCheck) {
657 generator.emitJump(end.get());
658 generator.emitLabel(realCall.get());
659 {
660 CallArguments callArguments(generator, m_args);
661 generator.emitMove(callArguments.thisRegister(), base.get());
662 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
663 }
664 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000665 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000666 if (generator.vm()->typeProfiler()) {
667 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
668 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000669 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000670 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000671}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000672
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000673static bool areTrivialApplyArguments(ArgumentsNode* args)
674{
675 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
676 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
677}
678
679RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
680{
681 // A few simple cases can be trivially handled as ordinary function calls.
682 // function.apply(), function.apply(arg) -> identical to function.call
683 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
684 bool mayBeCall = areTrivialApplyArguments(m_args);
685
686 RefPtr<Label> realCall = generator.newLabel();
687 RefPtr<Label> end = generator.newLabel();
688 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000689 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000690 RefPtr<RegisterID> function;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000691 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000692 bool emitCallCheck = !generator.isBuiltinFunction();
693 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000694 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000695 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
696 }
697 if (mayBeCall) {
698 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
699 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +0000700 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
701 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
702 RefPtr<RegisterID> profileHookRegister;
703 if (generator.shouldEmitProfileHooks())
704 profileHookRegister = generator.newTemporary();
705 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
706 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
707 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
708 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
709
710 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
711 {
712 RefPtr<Label> haveThis = generator.newLabel();
713 RefPtr<Label> end = generator.newLabel();
714 RefPtr<RegisterID> compareResult = generator.newTemporary();
715 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
716 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
717 generator.emitMove(thisRegister.get(), value);
718 generator.emitLoad(index.get(), jsNumber(1));
719 generator.emitJump(end.get());
720 generator.emitLabel(haveThis.get());
721 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
722 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
723 generator.emitMove(argumentsRegister.get(), value);
724 generator.emitLoad(index.get(), jsNumber(2));
725 generator.emitLabel(end.get());
726 };
727 generator.emitEnumeration(this, spread->expression(), extractor);
728 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
729 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +0000730 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
731 ASSERT(!m_args->m_listNode->m_next->m_next);
732 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.vm(), 0, 0);
oliver@apple.comfca9a922014-01-31 21:34:38 +0000733 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
734 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +0000735 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
736 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
737 } else {
738 m_args->m_listNode = m_args->m_listNode->m_next;
739 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
740 CallArguments callArguments(generator, m_args);
741 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000742 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000743 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000744 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000745 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +0000746 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000747 CallArguments callArguments(generator, m_args);
748 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
749 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000750 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000751 } else {
752 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
753 RefPtr<RegisterID> profileHookRegister;
754 if (generator.shouldEmitProfileHooks())
755 profileHookRegister = generator.newTemporary();
756 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
757 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
758 RefPtr<RegisterID> argsRegister;
759 ArgumentListNode* args = m_args->m_listNode->m_next;
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000760 if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()) && !generator.symbolTable().slowArguments())
oliver@apple.com71684cb2014-10-17 16:07:08 +0000761 argsRegister = generator.uncheckedLocalArgumentsRegister();
oliver@apple.comba848d12014-02-12 17:14:23 +0000762 else
763 argsRegister = generator.emitNode(args->m_expr);
764
765 // Function.prototype.apply ignores extra arguments, but we still
766 // need to evaluate them for side effects.
767 while ((args = args->m_next))
768 generator.emitNode(args->m_expr);
769
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000770 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
oliver@apple.comd04e0a02014-02-01 01:37:59 +0000771 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000772 if (emitCallCheck) {
773 generator.emitJump(end.get());
774 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000775 CallArguments callArguments(generator, m_args);
776 generator.emitMove(callArguments.thisRegister(), base.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000777 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000778 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000779 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000780 if (generator.vm()->typeProfiler()) {
781 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
782 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000783 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000784 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000785}
786
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000787// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000788
ggaren@apple.comf3036112013-04-27 23:14:04 +0000789static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000790{
ggaren@apple.comf3036112013-04-27 23:14:04 +0000791 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000792}
793
794static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
795{
ggaren@apple.comf3036112013-04-27 23:14:04 +0000796 if (dst == srcDst)
797 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
798 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
799 emitIncOrDec(generator, srcDst, oper);
800 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000801}
802
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000803RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000804{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000805 if (dst == generator.ignoredResult())
806 return PrefixNode::emitResolve(generator, dst);
807
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000808 ASSERT(m_expr->isResolveNode());
809 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
810 const Identifier& ident = resolve->identifier();
811
oliver@apple.com58c86752013-07-25 04:02:40 +0000812 if (Local local = generator.local(ident)) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000813 RegisterID* localReg = local.get();
oliver@apple.com58c86752013-07-25 04:02:40 +0000814 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +0000815 generator.emitReadOnlyExceptionIfNeeded();
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000816 localReg = generator.emitMove(generator.tempDestination(dst), localReg);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000817 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000818 RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
819 ASSERT(dst != localReg);
820 RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
821 generator.emitToNumber(tempDst.get(), localReg);
822 generator.emitMove(tempDstSrc.get(), localReg);
823 emitIncOrDec(generator, tempDstSrc.get(), m_operator);
824 generator.emitMove(localReg, tempDstSrc.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000825 if (generator.vm()->typeProfiler())
826 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000827 return tempDst.get();
828 }
829 return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg, m_operator);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000830 }
oliver@apple.com75f804e2013-03-07 00:25:20 +0000831
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000832 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000833 ResolveScopeInfo resolveScopeInfo;
834 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
835 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo);
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000836 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000837 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000838 if (generator.vm()->typeProfiler()) {
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000839 generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000840 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000841 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000842
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000843 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000844}
845
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000846RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000847{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000848 if (dst == generator.ignoredResult())
849 return PrefixNode::emitBracket(generator, dst);
850
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000851 ASSERT(m_expr->isBracketAccessorNode());
852 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
853 ExpressionNode* baseNode = bracketAccessor->base();
854 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000855
barraclough@apple.come3aa3f52012-09-06 00:55:46 +0000856 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000857 RefPtr<RegisterID> property = generator.emitNode(subscript);
858
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000859 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000860 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000861 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000862 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000863 generator.emitPutByVal(base.get(), property.get(), value.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000864 if (generator.vm()->typeProfiler()) {
865 generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
866 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000867 }
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000868 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000869}
870
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000871RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000872{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000873 if (dst == generator.ignoredResult())
874 return PrefixNode::emitDot(generator, dst);
875
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000876 ASSERT(m_expr->isDotAccessorNode());
877 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
878 ExpressionNode* baseNode = dotAccessor->base();
879 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000880
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000881 RefPtr<RegisterID> base = generator.emitNode(baseNode);
882
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000883 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000884 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000885 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000886 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000887 generator.emitPutById(base.get(), ident, value.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000888 if (generator.vm()->typeProfiler()) {
889 generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
890 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000891 }
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000892 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000893}
894
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000895RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000896{
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000897 if (m_expr->isResolveNode())
898 return emitResolve(generator, dst);
899
900 if (m_expr->isBracketAccessorNode())
901 return emitBracket(generator, dst);
902
903 if (m_expr->isDotAccessorNode())
904 return emitDot(generator, dst);
905
barraclough@apple.com4920ae92010-11-12 03:06:07 +0000906 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +0000907 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
908 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000909}
910
911// ------------------------------ DeleteResolveNode -----------------------------------
912
913RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
914{
oliver@apple.com58c86752013-07-25 04:02:40 +0000915 if (generator.local(m_ident).get())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000916 return generator.emitLoad(generator.finalDestination(dst), false);
917
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000918 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000919 ResolveScopeInfo resolveScopeInfo;
920 RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
oliver@apple.com58c86752013-07-25 04:02:40 +0000921 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000922}
923
924// ------------------------------ DeleteBracketNode -----------------------------------
925
926RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
927{
928 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
929 RegisterID* r1 = generator.emitNode(m_subscript);
930
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000931 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000932 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
933}
934
935// ------------------------------ DeleteDotNode -----------------------------------
936
937RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
938{
939 RegisterID* r0 = generator.emitNode(m_base);
940
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000941 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000942 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
943}
944
945// ------------------------------ DeleteValueNode -----------------------------------
946
947RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
948{
949 generator.emitNode(generator.ignoredResult(), m_expr);
950
951 // delete on a non-location expression ignores the value and returns true
952 return generator.emitLoad(generator.finalDestination(dst), true);
953}
954
955// ------------------------------ VoidNode -------------------------------------
956
957RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
958{
959 if (dst == generator.ignoredResult()) {
960 generator.emitNode(generator.ignoredResult(), m_expr);
961 return 0;
962 }
963 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
964 return generator.emitLoad(dst, jsUndefined());
965}
966
967// ------------------------------ TypeOfValueNode -----------------------------------
968
969RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
970{
oliver@apple.com58c86752013-07-25 04:02:40 +0000971 if (Local local = generator.local(m_ident)) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000972 if (dst == generator.ignoredResult())
973 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +0000974 return generator.emitTypeOf(generator.finalDestination(dst), local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000975 }
976
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000977 ResolveScopeInfo resolveScopeInfo;
978 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident, resolveScopeInfo);
979 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000980 if (dst == generator.ignoredResult())
981 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +0000982 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000983}
984
985// ------------------------------ TypeOfValueNode -----------------------------------
986
987RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
988{
989 if (dst == generator.ignoredResult()) {
990 generator.emitNode(generator.ignoredResult(), m_expr);
991 return 0;
992 }
993 RefPtr<RegisterID> src = generator.emitNode(m_expr);
994 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
995}
996
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000997// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000998
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000999RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001000{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001001 ASSERT(m_expr->isResolveNode());
1002 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1003 const Identifier& ident = resolve->identifier();
1004
oliver@apple.com58c86752013-07-25 04:02:40 +00001005 if (Local local = generator.local(ident)) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001006 RegisterID* localReg = local.get();
oliver@apple.com58c86752013-07-25 04:02:40 +00001007 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001008 generator.emitReadOnlyExceptionIfNeeded();
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001009 localReg = generator.emitMove(generator.tempDestination(dst), localReg);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001010 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001011 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1012 generator.emitMove(tempDst.get(), localReg);
1013 emitIncOrDec(generator, tempDst.get(), m_operator);
1014 generator.emitMove(localReg, tempDst.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001015 if (generator.vm()->typeProfiler())
1016 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001017 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1018 }
1019 emitIncOrDec(generator, localReg, m_operator);
1020 return generator.moveToDestinationIfNeeded(dst, localReg);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001021 }
1022
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001023 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001024 ResolveScopeInfo resolveScopeInfo;
1025 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident, resolveScopeInfo);
1026 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound, resolveScopeInfo);
oliver@apple.com58c86752013-07-25 04:02:40 +00001027 emitIncOrDec(generator, value.get(), m_operator);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001028 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound, resolveScopeInfo);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001029 if (generator.vm()->typeProfiler()) {
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001030 generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001031 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001032 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001033 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001034}
1035
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001036RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001037{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001038 ASSERT(m_expr->isBracketAccessorNode());
1039 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1040 ExpressionNode* baseNode = bracketAccessor->base();
1041 ExpressionNode* subscript = bracketAccessor->subscript();
1042
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001043 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001044 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001045 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1046
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001047 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001048 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001049 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001050 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001051 generator.emitPutByVal(base.get(), property.get(), value);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001052 if (generator.vm()->typeProfiler()) {
1053 generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1054 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001055 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001056 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1057}
1058
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001059RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001060{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001061 ASSERT(m_expr->isDotAccessorNode());
1062 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1063 ExpressionNode* baseNode = dotAccessor->base();
1064 const Identifier& ident = dotAccessor->identifier();
1065
1066 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001067 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1068
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001069 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001070 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001071 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001072 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001073 generator.emitPutById(base.get(), ident, value);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001074 if (generator.vm()->typeProfiler()) {
1075 generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1076 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001077 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001078 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1079}
1080
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001081RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001082{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001083 if (m_expr->isResolveNode())
1084 return emitResolve(generator, dst);
1085
1086 if (m_expr->isBracketAccessorNode())
1087 return emitBracket(generator, dst);
1088
1089 if (m_expr->isDotAccessorNode())
1090 return emitDot(generator, dst);
1091
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001092 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001093 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1094 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001095}
1096
1097// ------------------------------ Unary Operation Nodes -----------------------------------
1098
1099RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1100{
1101 RegisterID* src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001102 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001103 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
1104}
1105
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001106// ------------------------------ BitwiseNotNode -----------------------------------
1107
1108RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1109{
1110 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
1111 RegisterID* src1 = generator.emitNode(m_expr);
1112 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
1113}
1114
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001115// ------------------------------ LogicalNotNode -----------------------------------
1116
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001117void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001118{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001119 // reverse the true and false targets
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001120 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001121}
1122
1123
1124// ------------------------------ Binary Operation Nodes -----------------------------------
1125
1126// BinaryOpNode::emitStrcat:
1127//
1128// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1129// more values, where we can determine a set of separate op_add operations would be operating on
1130// string values.
1131//
1132// This function expects to be operating on a graph of AST nodes looking something like this:
1133//
1134// (a)... (b)
1135// \ /
1136// (+) (c)
1137// \ /
1138// [d] ((+))
1139// \ /
1140// [+=]
1141//
1142// The assignment operation is optional, if it exists the register holding the value on the
1143// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1144//
1145// The method should be called on the node at the root of the tree of regular binary add
1146// operations (marked in the diagram with a double set of parentheses). This node must
1147// be performing a string concatenation (determined by statically detecting that at least
1148// one child must be a string).
1149//
1150// Since the minimum number of values being concatenated together is expected to be 3, if
1151// a lhs to a concatenating assignment is not provided then the root add should have at
1152// least one left child that is also an add that can be determined to be operating on strings.
1153//
1154RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1155{
1156 ASSERT(isAdd());
1157 ASSERT(resultDescriptor().definitelyIsString());
1158
1159 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1160 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1161 // added first, and the leftmost child is never added, so the vector produced for the
1162 // example above will be [ c, b ].
1163 Vector<ExpressionNode*, 16> reverseExpressionList;
1164 reverseExpressionList.append(m_expr2);
1165
1166 // Examine the left child of the add. So long as this is a string add, add its right-child
1167 // to the list, and keep processing along the left fork.
1168 ExpressionNode* leftMostAddChild = m_expr1;
1169 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1170 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1171 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1172 }
1173
1174 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1175
1176 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1177 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1178 // op_strcat node handle its conversion if required).
1179 if (lhs)
1180 temporaryRegisters.append(generator.newTemporary());
1181
1182 // Emit code for the leftmost node ((a) in the example).
1183 temporaryRegisters.append(generator.newTemporary());
1184 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1185 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1186
1187 // Note on ordering of conversions:
1188 //
1189 // We maintain the same ordering of conversions as we would see if the concatenations
1190 // was performed as a sequence of adds (otherwise this optimization could change
1191 // behaviour should an object have been provided a valueOf or toString method).
1192 //
1193 // Considering the above example, the sequnce of execution is:
1194 // * evaluate operand (a)
1195 // * evaluate operand (b)
1196 // * convert (a) to primitive <- (this would be triggered by the first add)
1197 // * convert (b) to primitive <- (ditto)
1198 // * evaluate operand (c)
1199 // * convert (c) to primitive <- (this would be triggered by the second add)
1200 // And optionally, if there is an assignment:
1201 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1202 //
1203 // As such we do not plant an op to convert the leftmost child now. Instead, use
1204 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1205 // once the second node has been generated. However, if the leftmost child is an
1206 // immediate we can trivially determine that no conversion will be required.
1207 // If this is the case
1208 if (leftMostAddChild->isString())
1209 leftMostAddChildTempRegister = 0;
1210
1211 while (reverseExpressionList.size()) {
1212 ExpressionNode* node = reverseExpressionList.last();
1213 reverseExpressionList.removeLast();
1214
1215 // Emit the code for the current node.
1216 temporaryRegisters.append(generator.newTemporary());
1217 generator.emitNode(temporaryRegisters.last().get(), node);
1218
1219 // On the first iteration of this loop, when we first reach this point we have just
1220 // generated the second node, which means it is time to convert the leftmost operand.
1221 if (leftMostAddChildTempRegister) {
1222 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1223 leftMostAddChildTempRegister = 0; // Only do this once.
1224 }
1225 // Plant a conversion for this node, if necessary.
1226 if (!node->isString())
1227 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1228 }
1229 ASSERT(temporaryRegisters.size() >= 3);
1230
1231 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1232 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1233 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001234 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001235 // If there is an assignment convert the lhs now. This will also copy lhs to
1236 // the temporary register we allocated for it.
1237 if (lhs)
1238 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1239
1240 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1241}
1242
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001243void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1244{
1245 TriState branchCondition;
1246 ExpressionNode* branchExpression;
1247 tryFoldToBranch(generator, branchCondition, branchExpression);
1248
1249 if (branchCondition == MixedTriState)
1250 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1251 else if (branchCondition == TrueTriState)
1252 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1253 else
1254 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1255}
1256
1257static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1258{
1259 ResultType expressionType = branchExpression->resultDescriptor();
1260
1261 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1262 return true;
1263 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1264 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1265 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1266 return true;
1267
1268 return false;
1269}
1270
1271void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1272{
1273 branchCondition = MixedTriState;
1274 branchExpression = 0;
1275
1276 ConstantNode* constant = 0;
1277 if (m_expr1->isConstant()) {
1278 constant = static_cast<ConstantNode*>(m_expr1);
1279 branchExpression = m_expr2;
1280 } else if (m_expr2->isConstant()) {
1281 constant = static_cast<ConstantNode*>(m_expr2);
1282 branchExpression = m_expr1;
1283 }
1284
1285 if (!constant)
1286 return;
1287 ASSERT(branchExpression);
1288
1289 OpcodeID opcodeID = this->opcodeID();
1290 JSValue value = constant->jsValue(generator);
1291 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1292 if (!canFoldToBranch)
1293 return;
1294
1295 if (opcodeID == op_eq || opcodeID == op_stricteq)
1296 branchCondition = triState(value.pureToBoolean());
1297 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1298 branchCondition = triState(!value.pureToBoolean());
1299}
1300
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001301RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1302{
1303 OpcodeID opcodeID = this->opcodeID();
1304
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001305 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001306 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001307 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001308 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001309
1310 if (opcodeID == op_neq) {
1311 if (m_expr1->isNull() || m_expr2->isNull()) {
1312 RefPtr<RegisterID> src = generator.tempDestination(dst);
1313 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1314 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1315 }
1316 }
1317
oliver@apple.comece74042012-12-01 00:50:39 +00001318 ExpressionNode* left = m_expr1;
1319 ExpressionNode* right = m_expr2;
1320 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1321 if (left->isString())
1322 std::swap(left, right);
1323 }
1324
1325 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
1326 bool wasTypeof = generator.m_lastOpcodeID == op_typeof;
1327 RegisterID* src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001328 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001329 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001330 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1331 if (opcodeID == op_neq)
1332 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1333 else if (opcodeID == op_nstricteq)
1334 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1335 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001336 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001337 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1338 }
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001339 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
1340 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1341 return generator.emitUnaryOp(op_unsigned, result, result);
1342 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001343}
1344
1345RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1346{
1347 if (m_expr1->isNull() || m_expr2->isNull()) {
1348 RefPtr<RegisterID> src = generator.tempDestination(dst);
1349 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1350 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1351 }
1352
oliver@apple.comece74042012-12-01 00:50:39 +00001353 ExpressionNode* left = m_expr1;
1354 ExpressionNode* right = m_expr2;
1355 if (left->isString())
1356 std::swap(left, right);
1357
1358 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
1359 RegisterID* src2 = generator.emitNode(right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001360 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1361}
1362
1363RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1364{
oliver@apple.comece74042012-12-01 00:50:39 +00001365 ExpressionNode* left = m_expr1;
1366 ExpressionNode* right = m_expr2;
1367 if (left->isString())
1368 std::swap(left, right);
1369
1370 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
1371 RegisterID* src2 = generator.emitNode(right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001372 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1373}
1374
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001375RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1376{
1377 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1378 RegisterID* src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001379 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001380 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1381}
1382
1383RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1384{
1385 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1386 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001387 RefPtr<RegisterID> prototype = generator.newTemporary();
1388 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1389 RefPtr<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001390
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001391 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001392 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001393
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001394 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00001395 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001396
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001397 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com094dbd92012-09-22 01:18:54 +00001398 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001399 generator.emitLabel(target.get());
1400 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001401}
1402
1403// ------------------------------ LogicalOpNode ----------------------------
1404
1405RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1406{
1407 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1408 RefPtr<Label> target = generator.newLabel();
1409
1410 generator.emitNode(temp.get(), m_expr1);
1411 if (m_operator == OpLogicalAnd)
1412 generator.emitJumpIfFalse(temp.get(), target.get());
1413 else
1414 generator.emitJumpIfTrue(temp.get(), target.get());
1415 generator.emitNode(temp.get(), m_expr2);
1416 generator.emitLabel(target.get());
1417
1418 return generator.moveToDestinationIfNeeded(dst, temp.get());
1419}
1420
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001421void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001422{
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001423 RefPtr<Label> afterExpr1 = generator.newLabel();
1424 if (m_operator == OpLogicalAnd)
1425 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1426 else
1427 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1428 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001429
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001430 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001431}
1432
1433// ------------------------------ ConditionalNode ------------------------------
1434
1435RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1436{
1437 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1438 RefPtr<Label> beforeElse = generator.newLabel();
1439 RefPtr<Label> afterElse = generator.newLabel();
1440
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001441 RefPtr<Label> beforeThen = generator.newLabel();
1442 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1443 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001444
1445 generator.emitNode(newDst.get(), m_expr1);
1446 generator.emitJump(afterElse.get());
1447
1448 generator.emitLabel(beforeElse.get());
1449 generator.emitNode(newDst.get(), m_expr2);
1450
1451 generator.emitLabel(afterElse.get());
1452
1453 return newDst.get();
1454}
1455
1456// ------------------------------ ReadModifyResolveNode -----------------------------------
1457
1458// FIXME: should this be moved to be a method on BytecodeGenerator?
1459static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1460{
1461 OpcodeID opcodeID;
1462 switch (oper) {
1463 case OpMultEq:
1464 opcodeID = op_mul;
1465 break;
1466 case OpDivEq:
1467 opcodeID = op_div;
1468 break;
1469 case OpPlusEq:
1470 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1471 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1472 opcodeID = op_add;
1473 break;
1474 case OpMinusEq:
1475 opcodeID = op_sub;
1476 break;
1477 case OpLShift:
1478 opcodeID = op_lshift;
1479 break;
1480 case OpRShift:
1481 opcodeID = op_rshift;
1482 break;
1483 case OpURShift:
1484 opcodeID = op_urshift;
1485 break;
1486 case OpAndEq:
1487 opcodeID = op_bitand;
1488 break;
1489 case OpXOrEq:
1490 opcodeID = op_bitxor;
1491 break;
1492 case OpOrEq:
1493 opcodeID = op_bitor;
1494 break;
1495 case OpModEq:
1496 opcodeID = op_mod;
1497 break;
1498 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001499 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001500 return dst;
1501 }
1502
1503 RegisterID* src2 = generator.emitNode(m_right);
1504
1505 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1506 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1507 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001508 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001509 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1510 if (oper == OpURShift)
1511 return generator.emitUnaryOp(op_unsigned, result, result);
1512 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001513}
1514
1515RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1516{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00001517 JSTextPosition newDivot = divotStart() + m_ident.length();
oliver@apple.com58c86752013-07-25 04:02:40 +00001518 if (Local local = generator.local(m_ident)) {
1519 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001520 generator.emitReadOnlyExceptionIfNeeded();
oliver@apple.com58c86752013-07-25 04:02:40 +00001521 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
ggaren@apple.com6e309822012-09-05 21:44:43 +00001522 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001523
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001524 if (generator.vm()->typeProfiler()
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001525 || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001526 RefPtr<RegisterID> result = generator.newTemporary();
oliver@apple.com58c86752013-07-25 04:02:40 +00001527 generator.emitMove(result.get(), local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001528 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
oliver@apple.com58c86752013-07-25 04:02:40 +00001529 generator.emitMove(local.get(), result.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001530 generator.invalidateForInContextForLocal(local.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001531 if (generator.vm()->typeProfiler())
1532 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001533 return generator.moveToDestinationIfNeeded(dst, result.get());
1534 }
1535
oliver@apple.com58c86752013-07-25 04:02:40 +00001536 RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001537 generator.invalidateForInContextForLocal(local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001538 return generator.moveToDestinationIfNeeded(dst, result);
1539 }
1540
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001541 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001542 ResolveScopeInfo resolveScopeInfo;
1543 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
1544 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound, resolveScopeInfo);
oliver@apple.com58c86752013-07-25 04:02:40 +00001545 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001546 RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound, resolveScopeInfo);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001547 if (generator.vm()->typeProfiler()) {
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001548 generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001549 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001550 }
1551 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001552}
1553
1554// ------------------------------ AssignResolveNode -----------------------------------
1555
1556RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1557{
oliver@apple.com58c86752013-07-25 04:02:40 +00001558 if (Local local = generator.local(m_ident)) {
1559 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001560 generator.emitReadOnlyExceptionIfNeeded();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001561 return generator.emitNode(dst, m_right);
ggaren@apple.com6e309822012-09-05 21:44:43 +00001562 }
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001563 if (local.isSpecial() || generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001564 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1565 generator.emitNode(tempDst.get(), m_right);
1566 generator.emitMove(local.get(), tempDst.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001567 generator.invalidateForInContextForLocal(local.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001568 if (generator.vm()->typeProfiler())
1569 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001570 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1571 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001572 RegisterID* result = generator.emitNode(local.get(), m_right);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001573 generator.invalidateForInContextForLocal(local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001574 return generator.moveToDestinationIfNeeded(dst, result);
1575 }
1576
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001577 if (generator.isStrictMode())
1578 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001579 ResolveScopeInfo resolveScopeInfo;
1580 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001581 if (dst == generator.ignoredResult())
1582 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001583 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001584 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001585 RegisterID* returnResult = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001586 if (generator.vm()->typeProfiler()) {
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001587 generator.emitProfileType(result.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001588 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001589 }
1590 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001591}
1592
1593// ------------------------------ AssignDotNode -----------------------------------
1594
1595RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1596{
1597 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1598 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1599 RegisterID* result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001600 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001601 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1602 generator.emitPutById(base.get(), m_ident, forwardResult);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001603 if (generator.vm()->typeProfiler()) {
1604 generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1605 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001606 }
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001607 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001608}
1609
1610// ------------------------------ ReadModifyDotNode -----------------------------------
1611
1612RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1613{
1614 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1615
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001616 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001617 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001618 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 +00001619
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001620 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001621 RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001622 if (generator.vm()->typeProfiler()) {
1623 generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1624 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001625 }
1626 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001627}
1628
1629// ------------------------------ AssignErrorNode -----------------------------------
1630
1631RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1632{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001633 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001634}
1635
1636// ------------------------------ AssignBracketNode -----------------------------------
1637
1638RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1639{
1640 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1641 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1642 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1643 RegisterID* result = generator.emitNode(value.get(), m_right);
1644
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001645 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001646 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
akling@apple.come09d0422014-11-13 19:18:43 +00001647
1648 if (m_subscript->isString())
1649 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
1650 else
1651 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1652
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001653 if (generator.vm()->typeProfiler()) {
1654 generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1655 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001656 }
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001657 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001658}
1659
1660// ------------------------------ ReadModifyBracketNode -----------------------------------
1661
1662RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1663{
1664 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1665 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1666
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001667 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001668 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001669 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 +00001670
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001671 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001672 generator.emitPutByVal(base.get(), property.get(), updatedValue);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001673 if (generator.vm()->typeProfiler()) {
1674 generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1675 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001676 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001677
1678 return updatedValue;
1679}
1680
1681// ------------------------------ CommaNode ------------------------------------
1682
1683RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1684{
1685 ASSERT(m_expressions.size() > 1);
1686 for (size_t i = 0; i < m_expressions.size() - 1; i++)
1687 generator.emitNode(generator.ignoredResult(), m_expressions[i]);
1688 return generator.emitNode(dst, m_expressions.last());
1689}
1690
1691// ------------------------------ ConstDeclNode ------------------------------------
1692
1693RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1694{
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001695 // FIXME: This code does not match the behavior of const in Firefox.
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001696 if (Local local = generator.constLocal(m_ident)) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001697 if (!m_init)
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001698 return local.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001699
fpizlo@apple.com3378c482014-07-27 23:14:40 +00001700 // FIXME: Maybe call emitExpressionInfo here.
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001701 if (local.isSpecial() || generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001702 RefPtr<RegisterID> tempDst = generator.newTemporary();
1703 generator.emitNode(tempDst.get(), m_init);
1704 return generator.emitMove(local.get(), tempDst.get());
1705 }
1706
1707 return generator.emitNode(local.get(), m_init);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001708 }
1709
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001710 RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1711
oliver@apple.com75f804e2013-03-07 00:25:20 +00001712 if (generator.codeType() == GlobalCode)
1713 return generator.emitInitGlobalConst(m_ident, value.get());
1714
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001715 if (generator.codeType() != EvalCode) {
1716
1717 ResolveScopeInfo resolveScopeInfo;
1718 if (RefPtr<RegisterID> scope = generator.emitResolveConstantLocal(generator.newTemporary(), m_ident, resolveScopeInfo))
1719 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo);
1720
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001721 return value.get();
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001722 }
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001723
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001724 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001725 ResolveScopeInfo resolveScopeInfo;
1726 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
1727 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound, resolveScopeInfo);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001728}
1729
1730RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1731{
1732 RegisterID* result = 0;
1733 for (ConstDeclNode* n = this; n; n = n->m_next)
1734 result = n->emitCodeSingle(generator);
1735
1736 return result;
1737}
1738
1739// ------------------------------ ConstStatementNode -----------------------------
1740
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001741void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001742{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001743 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001744 generator.emitNode(m_next);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001745}
1746
1747// ------------------------------ SourceElements -------------------------------
1748
1749
1750inline StatementNode* SourceElements::lastStatement() const
1751{
1752 size_t size = m_statements.size();
1753 return size ? m_statements[size - 1] : 0;
1754}
1755
1756inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1757{
1758 size_t size = m_statements.size();
1759 for (size_t i = 0; i < size; ++i)
1760 generator.emitNode(dst, m_statements[i]);
1761}
1762
1763// ------------------------------ BlockNode ------------------------------------
1764
1765inline StatementNode* BlockNode::lastStatement() const
1766{
1767 return m_statements ? m_statements->lastStatement() : 0;
1768}
1769
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00001770inline StatementNode* BlockNode::singleStatement() const
1771{
1772 return m_statements ? m_statements->singleStatement() : 0;
1773}
1774
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001775void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001776{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001777 if (!m_statements)
1778 return;
1779 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001780}
1781
1782// ------------------------------ EmptyStatementNode ---------------------------
1783
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001784void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001785{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001786 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001787}
1788
1789// ------------------------------ DebuggerStatementNode ---------------------------
1790
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001791void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001792{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001793 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001794}
1795
1796// ------------------------------ ExprStatementNode ----------------------------
1797
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001798void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001799{
1800 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001801 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001802 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001803}
1804
1805// ------------------------------ VarStatementNode ----------------------------
1806
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001807void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001808{
1809 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001810 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001811 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001812}
1813
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001814// ------------------------------ EmptyVarExpression ----------------------------
1815
1816RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1817{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001818 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001819 return nullptr;
1820
1821 if (Local local = generator.local(m_ident))
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001822 generator.emitProfileType(local.get(), ProfileTypeBytecodeHasGlobalID, nullptr);
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001823 else {
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001824 ResolveScopeInfo resolveScopeInfo;
1825 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident, resolveScopeInfo);
1826 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound, resolveScopeInfo);
1827 generator.emitProfileType(value.get(), resolveScopeInfo.isLocal() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001828 }
1829
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001830 generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001831
1832 // It's safe to return null here because this node will always be a child node of VarStatementNode which ignores our return value.
1833 return nullptr;
1834}
1835
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001836// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001837
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001838static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001839{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001840 if (statementNode->isBlock())
1841 return static_cast<BlockNode*>(statementNode)->singleStatement();
1842 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001843}
1844
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001845bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
1846 Label*& trueTarget, FallThroughMode& fallThroughMode)
1847{
1848 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
1849 if (!singleStatement)
1850 return false;
1851
1852 if (singleStatement->isBreak()) {
1853 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
1854 Label* target = breakNode->trivialTarget(generator);
1855 if (!target)
1856 return false;
1857 trueTarget = target;
1858 fallThroughMode = FallThroughMeansFalse;
1859 return true;
1860 }
1861
1862 if (singleStatement->isContinue()) {
1863 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
1864 Label* target = continueNode->trivialTarget(generator);
1865 if (!target)
1866 return false;
1867 trueTarget = target;
1868 fallThroughMode = FallThroughMeansFalse;
1869 return true;
1870 }
1871
1872 return false;
1873}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001874
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001875void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001876{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001877 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00001878
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001879 RefPtr<Label> beforeThen = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001880 RefPtr<Label> beforeElse = generator.newLabel();
1881 RefPtr<Label> afterElse = generator.newLabel();
1882
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001883 Label* trueTarget = beforeThen.get();
1884 Label* falseTarget = beforeElse.get();
1885 FallThroughMode fallThroughMode = FallThroughMeansTrue;
1886 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
1887
1888 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001889 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001890
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001891 if (!didFoldIfBlock) {
1892 generator.emitNode(dst, m_ifBlock);
1893 if (m_elseBlock)
1894 generator.emitJump(afterElse.get());
1895 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001896
1897 generator.emitLabel(beforeElse.get());
1898
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001899 if (m_elseBlock)
1900 generator.emitNode(dst, m_elseBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001901
1902 generator.emitLabel(afterElse.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001903}
1904
1905// ------------------------------ DoWhileNode ----------------------------------
1906
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001907void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001908{
oliver@apple.com6a976452013-03-11 21:02:39 +00001909 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001910
1911 RefPtr<Label> topOfLoop = generator.newLabel();
1912 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001913 generator.emitLoopHint();
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001914 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001915
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001916 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001917
1918 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001919 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001920 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001921
1922 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001923}
1924
1925// ------------------------------ WhileNode ------------------------------------
1926
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001927void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001928{
oliver@apple.com6a976452013-03-11 21:02:39 +00001929 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001930 RefPtr<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001931
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001932 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->startOffset(), m_expr->lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001933 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001934
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001935 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001936 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001937
1938 generator.emitNode(dst, m_statement);
1939
1940 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001941 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001942
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001943 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001944
1945 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001946}
1947
1948// ------------------------------ ForNode --------------------------------------
1949
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001950void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001951{
oliver@apple.com6a976452013-03-11 21:02:39 +00001952 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001953
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001954 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001955
1956 if (m_expr1)
1957 generator.emitNode(generator.ignoredResult(), m_expr1);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001958
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001959 RefPtr<Label> topOfLoop = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001960 if (m_expr2)
1961 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001962
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001963 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001964 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001965
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001966 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001967
1968 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001969 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001970 if (m_expr3)
1971 generator.emitNode(generator.ignoredResult(), m_expr3);
1972
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001973 if (m_expr2)
1974 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1975 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001976 generator.emitJump(topOfLoop.get());
1977
1978 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001979}
1980
1981// ------------------------------ ForInNode ------------------------------------
1982
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001983RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001984{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001985 if (m_lexpr->isResolveNode()) {
1986 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
oliver@apple.com58c86752013-07-25 04:02:40 +00001987 Local local = generator.local(ident);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001988 return local.get();
1989 }
1990
1991 if (m_lexpr->isDeconstructionNode()) {
1992 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
1993 auto binding = assignNode->bindings();
1994 if (!binding->isBindingNode())
1995 return nullptr;
1996
1997 auto simpleBinding = static_cast<BindingNode*>(binding);
1998 const Identifier& ident = simpleBinding->boundProperty();
1999 Local local = generator.local(ident);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002000 if (local.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002001 return nullptr;
2002 return local.get();
2003 }
2004
2005 return nullptr;
2006}
2007
2008void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2009{
2010 if (m_lexpr->isResolveNode()) {
2011 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2012 Local local = generator.local(ident);
2013 if (local.get())
2014 generator.emitMove(local.get(), propertyName);
2015 else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002016 if (generator.isStrictMode())
2017 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002018 ResolveScopeInfo resolveScopeInfo;
2019 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002020 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002021 generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002022 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002023 return;
2024 }
2025 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002026 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2027 const Identifier& ident = assignNode->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002028 RegisterID* base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002029 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002030 generator.emitPutById(base, ident, propertyName);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002031 return;
2032 }
2033 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002034 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002035 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2036 RegisterID* subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002037 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002038 generator.emitPutByVal(base.get(), subscript, propertyName);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002039 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002040 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002041
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002042 if (m_lexpr->isDeconstructionNode()) {
2043 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
2044 auto binding = assignNode->bindings();
2045 if (!binding->isBindingNode()) {
2046 assignNode->bindings()->bindValue(generator, propertyName);
2047 return;
2048 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002049
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002050 auto simpleBinding = static_cast<BindingNode*>(binding);
2051 const Identifier& ident = simpleBinding->boundProperty();
2052 Local local = generator.local(ident);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002053 if (!local.get() || local.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002054 assignNode->bindings()->bindValue(generator, propertyName);
2055 return;
2056 }
2057 generator.emitMove(local.get(), propertyName);
2058 return;
2059 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002060
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002061 RELEASE_ASSERT_NOT_REACHED();
2062}
2063
2064void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
2065{
2066 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002067 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002068 return;
2069 }
2070
2071 RefPtr<Label> end = generator.newLabel();
2072
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002073 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002074
2075 RefPtr<RegisterID> base = generator.newTemporary();
2076 RefPtr<RegisterID> length;
2077 RefPtr<RegisterID> structureEnumerator;
2078 generator.emitNode(base.get(), m_expr);
2079 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
2080
2081 // Indexed property loop.
2082 {
2083 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2084 RefPtr<Label> loopStart = generator.newLabel();
2085 RefPtr<Label> loopEnd = generator.newLabel();
2086
2087 length = generator.emitGetEnumerableLength(generator.newTemporary(), base.get());
2088 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2089 RefPtr<RegisterID> propertyName = generator.newTemporary();
2090
2091 generator.emitLabel(loopStart.get());
2092 generator.emitLoopHint();
2093
2094 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2095 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2096 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
2097 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2098
2099 generator.emitToIndexString(propertyName.get(), i.get());
2100 this->emitLoopHeader(generator, propertyName.get());
2101
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002102 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002103 generator.emitNode(dst, m_statement);
2104 generator.popIndexedForInScope(local.get());
2105
2106 generator.emitLabel(scope->continueTarget());
2107 generator.emitInc(i.get());
2108 generator.emitJump(loopStart.get());
2109
2110 generator.emitLabel(scope->breakTarget());
2111 generator.emitJump(end.get());
2112 generator.emitLabel(loopEnd.get());
2113 }
2114
2115 // Structure property loop.
2116 {
2117 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2118 RefPtr<Label> loopStart = generator.newLabel();
2119 RefPtr<Label> loopEnd = generator.newLabel();
2120
2121 structureEnumerator = generator.emitGetStructurePropertyEnumerator(generator.newTemporary(), base.get(), length.get());
2122 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2123 RefPtr<RegisterID> propertyName = generator.newTemporary();
2124 generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
2125
2126 generator.emitLabel(loopStart.get());
2127 generator.emitLoopHint();
2128
2129 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2130 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2131 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), structureEnumerator.get());
2132 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2133
2134 this->emitLoopHeader(generator, propertyName.get());
2135
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002136 generator.pushStructureForInScope(local.get(), i.get(), propertyName.get(), structureEnumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002137 generator.emitNode(dst, m_statement);
2138 generator.popStructureForInScope(local.get());
2139
2140 generator.emitLabel(scope->continueTarget());
2141 generator.emitInc(i.get());
2142 generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
2143 generator.emitJump(loopStart.get());
2144
2145 generator.emitLabel(scope->breakTarget());
2146 generator.emitJump(end.get());
2147 generator.emitLabel(loopEnd.get());
2148 }
2149
2150 // Generic property loop.
2151 {
2152 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2153 RefPtr<Label> loopStart = generator.newLabel();
2154 RefPtr<Label> loopEnd = generator.newLabel();
2155
2156 RefPtr<RegisterID> genericEnumerator = generator.emitGetGenericPropertyEnumerator(generator.newTemporary(), base.get(), length.get(), structureEnumerator.get());
2157 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2158 RefPtr<RegisterID> propertyName = generator.newTemporary();
2159
2160 generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
2161 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2162 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2163
2164 generator.emitLabel(loopStart.get());
2165 generator.emitLoopHint();
2166
2167 this->emitLoopHeader(generator, propertyName.get());
2168
2169 generator.emitNode(dst, m_statement);
2170
2171 generator.emitLabel(scope->continueTarget());
2172 generator.emitInc(i.get());
2173 generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
2174 generator.emitUnaryOp(op_eq_null, result.get(), propertyName.get());
2175 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2176
2177 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
2178 generator.emitJumpIfTrue(result.get(), loopStart.get());
2179 generator.emitJump(scope->continueTarget());
2180
2181 generator.emitLabel(scope->breakTarget());
2182 generator.emitJump(end.get());
2183 generator.emitLabel(loopEnd.get());
2184 }
2185
2186 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2187 generator.emitLabel(end.get());
2188}
2189
2190void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2191{
2192 this->emitMultiLoopBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002193}
2194
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002195// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002196void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2197{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002198 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002199 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002200 return;
2201 }
2202
oliver@apple.com72f8a822013-10-17 01:02:34 +00002203 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2204
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002205 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002206 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002207 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002208 if (m_lexpr->isResolveNode()) {
2209 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
2210 if (Local local = generator.local(ident))
2211 generator.emitMove(local.get(), value);
2212 else {
2213 if (generator.isStrictMode())
2214 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002215 ResolveScopeInfo resolveScopeInfo;
2216 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident, resolveScopeInfo);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002217 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002218 generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002219 }
2220 } else if (m_lexpr->isDotAccessorNode()) {
2221 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2222 const Identifier& ident = assignNode->identifier();
2223 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2224
2225 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2226 generator.emitPutById(base.get(), ident, value);
2227 } else if (m_lexpr->isBracketAccessorNode()) {
2228 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
2229 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2230 RegisterID* subscript = generator.emitNode(assignNode->subscript());
2231
2232 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2233 generator.emitPutByVal(base.get(), subscript, value);
2234 } else {
2235 ASSERT(m_lexpr->isDeconstructionNode());
2236 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00002237 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002238 }
oliver@apple.com72f8a822013-10-17 01:02:34 +00002239 generator.emitNode(dst, m_statement);
2240 };
2241 generator.emitEnumeration(this, m_expr, extractor);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002242}
2243
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002244// ------------------------------ ContinueNode ---------------------------------
2245
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002246Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
2247{
2248 if (generator.shouldEmitDebugHooks())
2249 return 0;
2250
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002251 LabelScopePtr scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002252 ASSERT(scope);
2253
2254 if (generator.scopeDepth() != scope->scopeDepth())
2255 return 0;
2256
2257 return scope->continueTarget();
2258}
2259
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002260void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002261{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002262 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002263
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002264 LabelScopePtr scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002265 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002266
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002267 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002268 generator.emitJump(scope->continueTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002269}
2270
2271// ------------------------------ BreakNode ------------------------------------
2272
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002273Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
2274{
2275 if (generator.shouldEmitDebugHooks())
2276 return 0;
2277
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002278 LabelScopePtr scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002279 ASSERT(scope);
2280
2281 if (generator.scopeDepth() != scope->scopeDepth())
2282 return 0;
2283
2284 return scope->breakTarget();
2285}
2286
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002287void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002288{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002289 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002290
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002291 LabelScopePtr scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002292 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002293
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002294 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002295 generator.emitJump(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002296}
2297
2298// ------------------------------ ReturnNode -----------------------------------
2299
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002300void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002301{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002302 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002303 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002304
2305 if (dst == generator.ignoredResult())
2306 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002307
2308 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002309 if (generator.vm()->typeProfiler()) {
2310 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, nullptr);
2311 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002312 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002313 if (generator.scopeDepth()) {
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002314 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002315 generator.emitPopScopes(generator.scopeRegister(), 0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002316 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002317
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002318 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002319 generator.emitReturn(returnRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002320}
2321
2322// ------------------------------ WithNode -------------------------------------
2323
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002324void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002325{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002326 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.com170d6f22012-09-02 21:27:23 +00002327
2328 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002329 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002330 generator.emitPushWithScope(generator.scopeRegister(), scope.get());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002331 generator.emitNode(dst, m_statement);
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002332 generator.emitPopScope(generator.scopeRegister());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002333}
2334
2335// ------------------------------ CaseClauseNode --------------------------------
2336
2337inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2338{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002339 if (!m_statements)
2340 return;
2341 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002342}
2343
2344// ------------------------------ CaseBlockNode --------------------------------
2345
2346enum SwitchKind {
2347 SwitchUnset = 0,
2348 SwitchNumber = 1,
2349 SwitchString = 2,
2350 SwitchNeither = 3
2351};
2352
2353static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2354{
2355 for (; list; list = list->getNext()) {
2356 ExpressionNode* clauseExpression = list->getClause()->expr();
2357 literalVector.append(clauseExpression);
2358 if (clauseExpression->isNumber()) {
2359 double value = static_cast<NumberNode*>(clauseExpression)->value();
2360 int32_t intVal = static_cast<int32_t>(value);
2361 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
2362 typeForTable = SwitchNeither;
2363 break;
2364 }
2365 if (intVal < min_num)
2366 min_num = intVal;
2367 if (intVal > max_num)
2368 max_num = intVal;
2369 typeForTable = SwitchNumber;
2370 continue;
2371 }
2372 if (clauseExpression->isString()) {
2373 if (typeForTable & ~SwitchString) {
2374 typeForTable = SwitchNeither;
2375 break;
2376 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00002377 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00002378 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00002379 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002380 if (intVal < min_num)
2381 min_num = intVal;
2382 if (intVal > max_num)
2383 max_num = intVal;
2384 }
2385 typeForTable = SwitchString;
2386 continue;
2387 }
2388 typeForTable = SwitchNeither;
2389 break;
2390 }
2391}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002392
2393static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002394{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002395 size_t length = 0;
2396 for (ClauseListNode* node = list1; node; node = node->getNext())
2397 ++length;
2398 for (ClauseListNode* node = list2; node; node = node->getNext())
2399 ++length;
2400 return length;
2401}
2402
2403SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2404{
2405 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
2406 return SwitchInfo::SwitchNone;
2407
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002408 SwitchKind typeForTable = SwitchUnset;
2409 bool singleCharacterSwitch = true;
2410
2411 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2412 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2413
2414 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2415 return SwitchInfo::SwitchNone;
2416
2417 if (typeForTable == SwitchNumber) {
2418 int32_t range = max_num - min_num;
2419 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2420 return SwitchInfo::SwitchImmediate;
2421 return SwitchInfo::SwitchNone;
2422 }
2423
2424 ASSERT(typeForTable == SwitchString);
2425
2426 if (singleCharacterSwitch) {
2427 int32_t range = max_num - min_num;
2428 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2429 return SwitchInfo::SwitchCharacter;
2430 }
2431
2432 return SwitchInfo::SwitchString;
2433}
2434
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002435void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002436{
2437 RefPtr<Label> defaultLabel;
2438 Vector<RefPtr<Label>, 8> labelVector;
2439 Vector<ExpressionNode*, 8> literalVector;
2440 int32_t min_num = std::numeric_limits<int32_t>::max();
2441 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002442 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002443
2444 if (switchType != SwitchInfo::SwitchNone) {
2445 // Prepare the various labels
2446 for (uint32_t i = 0; i < literalVector.size(); i++)
2447 labelVector.append(generator.newLabel());
2448 defaultLabel = generator.newLabel();
2449 generator.beginSwitch(switchExpression, switchType);
2450 } else {
2451 // Setup jumps
2452 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2453 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2454 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2455 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2456 labelVector.append(generator.newLabel());
2457 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2458 }
2459
2460 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2461 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2462 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2463 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2464 labelVector.append(generator.newLabel());
2465 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2466 }
2467 defaultLabel = generator.newLabel();
2468 generator.emitJump(defaultLabel.get());
2469 }
2470
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002471 size_t i = 0;
2472 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2473 generator.emitLabel(labelVector[i++].get());
2474 list->getClause()->emitBytecode(generator, dst);
2475 }
2476
2477 if (m_defaultClause) {
2478 generator.emitLabel(defaultLabel.get());
2479 m_defaultClause->emitBytecode(generator, dst);
2480 }
2481
2482 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2483 generator.emitLabel(labelVector[i++].get());
2484 list->getClause()->emitBytecode(generator, dst);
2485 }
2486 if (!m_defaultClause)
2487 generator.emitLabel(defaultLabel.get());
2488
2489 ASSERT(i == labelVector.size());
2490 if (switchType != SwitchInfo::SwitchNone) {
2491 ASSERT(labelVector.size() == literalVector.size());
2492 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2493 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002494}
2495
2496// ------------------------------ SwitchNode -----------------------------------
2497
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002498void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002499{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002500 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002501
oliver@apple.com6a976452013-03-11 21:02:39 +00002502 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002503
2504 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002505 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002506
2507 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002508}
2509
2510// ------------------------------ LabelNode ------------------------------------
2511
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002512void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002513{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002514 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002515
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002516 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002517
oliver@apple.com6a976452013-03-11 21:02:39 +00002518 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002519 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002520
2521 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002522}
2523
2524// ------------------------------ ThrowNode ------------------------------------
2525
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002526void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002527{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002528 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002529
2530 if (dst == generator.ignoredResult())
2531 dst = 0;
2532 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002533 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002534 generator.emitThrow(expr.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002535}
2536
2537// ------------------------------ TryNode --------------------------------------
2538
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002539void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002540{
2541 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2542 // optimizer knows they may be jumped to from anywhere.
2543
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002544 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002545
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002546 ASSERT(m_catchBlock || m_finallyBlock);
2547
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002548 RefPtr<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002549 generator.emitLabel(tryStartLabel.get());
2550
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002551 if (m_finallyBlock)
2552 generator.pushFinallyContext(m_finallyBlock);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002553 TryData* tryData = generator.pushTry(tryStartLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002554
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002555 generator.emitNode(dst, m_tryBlock);
2556
2557 if (m_catchBlock) {
2558 RefPtr<Label> catchEndLabel = generator.newLabel();
2559
2560 // Normal path: jump over the catch block.
2561 generator.emitJump(catchEndLabel.get());
2562
2563 // Uncaught exception path: the catch block.
2564 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002565 RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
2566
2567 if (m_finallyBlock) {
2568 // If the catch block throws an exception and we have a finally block, then the finally
2569 // block should "catch" that exception.
2570 tryData = generator.pushTry(here.get());
2571 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002572
2573 generator.emitPushCatchScope(generator.scopeRegister(), m_exceptionIdent, exceptionRegister.get(), DontDelete);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002574 generator.emitNode(dst, m_catchBlock);
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002575 generator.emitPopScope(generator.scopeRegister());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002576 generator.emitLabel(catchEndLabel.get());
2577 }
2578
2579 if (m_finallyBlock) {
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002580 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2581
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002582 generator.popFinallyContext();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002583
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002584 RefPtr<Label> finallyEndLabel = generator.newLabel();
2585
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002586 // Normal path: run the finally code, and jump to the end.
2587 generator.emitNode(dst, m_finallyBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002588 generator.emitJump(finallyEndLabel.get());
2589
2590 // Uncaught exception path: invoke the finally block, then re-throw the exception.
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002591 RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002592 generator.emitNode(dst, m_finallyBlock);
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002593 generator.emitThrow(tempExceptionRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002594
2595 generator.emitLabel(finallyEndLabel.get());
2596 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002597}
2598
2599// ------------------------------ ScopeNode -----------------------------
2600
2601inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2602{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002603 if (!m_statements)
2604 return;
2605 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002606}
2607
2608// ------------------------------ ProgramNode -----------------------------
2609
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002610void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002611{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002612 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002613
2614 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2615 generator.emitLoad(dstRegister.get(), jsUndefined());
2616 emitStatementsBytecode(generator, dstRegister.get());
2617
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002618 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002619 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002620}
2621
2622// ------------------------------ EvalNode -----------------------------
2623
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002624void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002625{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002626 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002627
2628 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2629 generator.emitLoad(dstRegister.get(), jsUndefined());
2630 emitStatementsBytecode(generator, dstRegister.get());
2631
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002632 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002633 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002634}
2635
2636// ------------------------------ FunctionBodyNode -----------------------------
2637
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002638void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002639{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002640 if (generator.vm()->typeProfiler()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002641 for (size_t i = 0; i < m_parameters->size(); i++) {
2642 // FIXME: Handle Destructuring assignments into arguments.
2643 if (!m_parameters->at(i)->isBindingNode())
2644 continue;
2645 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i));
2646 RegisterID reg(CallFrame::argumentOffset(i));
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002647 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, nullptr);
2648 generator.emitTypeProfilerExpressionInfo(parameter->divotStart(), parameter->divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002649 }
2650 }
2651
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002652 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002653 emitStatementsBytecode(generator, generator.ignoredResult());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002654
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002655 StatementNode* singleStatement = this->singleStatement();
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002656 ReturnNode* returnNode = 0;
2657
2658 // Check for a return statement at the end of a function composed of a single block.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002659 if (singleStatement && singleStatement->isBlock()) {
2660 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2661 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002662 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002663 }
2664
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002665 // If there is no return we must automatically insert one.
2666 if (!returnNode) {
2667 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002668 if (generator.vm()->typeProfiler())
2669 generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement, nullptr); // 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 +00002670 ASSERT(startOffset() >= lineStartOffset());
2671 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002672 generator.emitReturn(r0);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002673 return;
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002674 }
2675
2676 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
ggaren@apple.com7426f922010-07-16 04:58:30 +00002677 if (static_cast<BlockNode*>(singleStatement)->singleStatement()) {
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002678 ExpressionNode* returnValueExpression = returnNode->value();
2679 if (returnValueExpression && returnValueExpression->isSubtract()) {
2680 ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
2681 ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
ggaren@apple.com50c5ac22011-11-14 23:16:27 +00002682 if (lhsExpression->isResolveNode()
2683 && rhsExpression->isResolveNode()
2684 && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
2685 && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
2686
2687 generator.setIsNumericCompareFunction(true);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002688 }
2689 }
2690 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002691}
2692
2693// ------------------------------ FuncDeclNode ---------------------------------
2694
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002695void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002696{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002697}
2698
2699// ------------------------------ FuncExprNode ---------------------------------
2700
2701RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2702{
2703 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2704}
oliver@apple.comd055db62013-10-02 19:11:04 +00002705
2706// ------------------------------ DeconstructingAssignmentNode -----------------
2707RegisterID* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2708{
2709 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
2710 return result;
2711 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
2712 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00002713 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002714 return generator.moveToDestinationIfNeeded(dst, initializer.get());
2715}
2716
2717DeconstructionPatternNode::~DeconstructionPatternNode()
2718{
2719}
2720
oliver@apple.com47784d62013-10-25 21:31:36 +00002721void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00002722{
2723 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2724 auto target = m_targetPatterns[i];
2725 if (!target)
2726 continue;
2727 RefPtr<RegisterID> temp = generator.newTemporary();
2728 generator.emitLoad(temp.get(), jsNumber(i));
2729 generator.emitGetByVal(temp.get(), rhs, temp.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00002730 target->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002731 }
2732}
2733
2734RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
2735{
2736 if (rhs->isResolveNode()
2737 && generator.willResolveToArguments(static_cast<ResolveNode*>(rhs)->identifier())
oliver@apple.com71684cb2014-10-17 16:07:08 +00002738 && generator.hasSafeLocalArgumentsRegister()&& !generator.symbolTable().slowArguments()) {
oliver@apple.comd055db62013-10-02 19:11:04 +00002739 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2740 auto target = m_targetPatterns[i];
2741 if (!target)
2742 continue;
2743
2744 RefPtr<RegisterID> temp = generator.newTemporary();
2745 generator.emitLoad(temp.get(), jsNumber(i));
oliver@apple.com71684cb2014-10-17 16:07:08 +00002746 generator.emitGetArgumentByVal(temp.get(), generator.uncheckedLocalArgumentsRegister(), temp.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00002747 target->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002748 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00002749 if (dst == generator.ignoredResult() || !dst)
2750 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
2751 Local local = generator.local(generator.vm()->propertyNames->arguments);
2752 return generator.moveToDestinationIfNeeded(dst, local.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002753 }
2754 if (!rhs->isSimpleArray())
2755 return 0;
oliver@apple.com47784d62013-10-25 21:31:36 +00002756
oliver@apple.com2bae57a2013-11-12 20:55:29 +00002757 RefPtr<RegisterID> resultRegister;
2758 if (dst && dst != generator.ignoredResult())
2759 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00002760 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
2761 Vector<ExpressionNode*> elements;
2762 for (; elementNodes; elementNodes = elementNodes->next())
2763 elements.append(elementNodes->value());
2764 if (m_targetPatterns.size() != elements.size())
2765 return 0;
2766 Vector<RefPtr<RegisterID>> registers;
2767 registers.reserveCapacity(m_targetPatterns.size());
2768 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2769 registers.uncheckedAppend(generator.newTemporary());
2770 generator.emitNode(registers.last().get(), elements[i]);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00002771 if (resultRegister)
2772 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002773 }
2774
2775 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2776 if (m_targetPatterns[i])
oliver@apple.com47784d62013-10-25 21:31:36 +00002777 m_targetPatterns[i]->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002778 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00002779 if (resultRegister)
2780 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00002781 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00002782}
2783
2784void ArrayPatternNode::toString(StringBuilder& builder) const
2785{
2786 builder.append('[');
2787 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2788 if (!m_targetPatterns[i]) {
2789 builder.append(',');
2790 continue;
2791 }
2792 m_targetPatterns[i]->toString(builder);
2793 if (i < m_targetPatterns.size() - 1)
2794 builder.append(',');
2795 }
2796 builder.append(']');
2797}
2798
2799void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2800{
2801 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2802 if (DeconstructionPatternNode* node = m_targetPatterns[i].get())
2803 node->collectBoundIdentifiers(identifiers);
2804 }
2805}
2806
2807void ObjectPatternNode::toString(StringBuilder& builder) const
2808{
2809 builder.append('{');
2810 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2811 if (m_targetPatterns[i].wasString) {
2812 builder.append('"');
2813 escapeStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
2814 builder.append('"');
2815 } else
2816 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002817 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00002818 m_targetPatterns[i].pattern->toString(builder);
2819 if (i < m_targetPatterns.size() - 1)
2820 builder.append(',');
2821 }
2822 builder.append('}');
2823}
2824
oliver@apple.com47784d62013-10-25 21:31:36 +00002825void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00002826{
2827 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2828 auto& target = m_targetPatterns[i];
2829 RefPtr<RegisterID> temp = generator.newTemporary();
2830 generator.emitGetById(temp.get(), rhs, target.propertyName);
oliver@apple.com47784d62013-10-25 21:31:36 +00002831 target.pattern->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002832 }
2833}
2834
2835void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2836{
2837 for (size_t i = 0; i < m_targetPatterns.size(); i++)
2838 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
2839}
2840
oliver@apple.com47784d62013-10-25 21:31:36 +00002841void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00002842{
2843 if (Local local = generator.local(m_boundProperty)) {
2844 if (local.isReadOnly()) {
2845 generator.emitReadOnlyExceptionIfNeeded();
2846 return;
2847 }
2848 generator.emitMove(local.get(), value);
saambarati1@gmail.comaf59ca42014-08-29 22:52:51 +00002849 if (generator.vm()->typeProfiler())
2850 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
oliver@apple.comd055db62013-10-02 19:11:04 +00002851 return;
2852 }
2853 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00002854 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002855 ResolveScopeInfo resolveScopeInfo;
2856 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty, resolveScopeInfo);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00002857 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002858 generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, resolveScopeInfo);
saambarati1@gmail.comaf59ca42014-08-29 22:52:51 +00002859 if (generator.vm()->typeProfiler()) {
oliver@apple.comf129dfb2014-10-02 20:35:58 +00002860 generator.emitProfileType(value, resolveScopeInfo.isLocal() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty);
saambarati1@gmail.comaf59ca42014-08-29 22:52:51 +00002861 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
2862 }
oliver@apple.comd055db62013-10-02 19:11:04 +00002863 return;
2864}
2865
2866void BindingNode::toString(StringBuilder& builder) const
2867{
2868 builder.append(m_boundProperty.string());
2869}
2870
2871void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2872{
2873 identifiers.append(m_boundProperty);
2874}
oliver@apple.com72f8a822013-10-17 01:02:34 +00002875
2876RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2877{
2878 RELEASE_ASSERT_NOT_REACHED();
2879 return 0;
2880}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002881
2882} // namespace JSC