blob: 64c3e9a87b00be3df935dbbd73bc953aa293167c [file] [log] [blame]
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00004* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013, 2015 Apple Inc. All rights reserved.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00005* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +00008 * Copyright (C) 2012 Igalia, S.L.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00009*
10* This library is free software; you can redistribute it and/or
11* modify it under the terms of the GNU Library General Public
12* License as published by the Free Software Foundation; either
13* version 2 of the License, or (at your option) any later version.
14*
15* This library is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18* Library General Public License for more details.
19*
20* You should have received a copy of the GNU Library General Public License
21* along with this library; see the file COPYING.LIB. If not, write to
22* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23* Boston, MA 02110-1301, USA.
24*
25*/
26
27#include "config.h"
28#include "Nodes.h"
oliver@apple.comd04e0a02014-02-01 01:37:59 +000029#include "NodeConstructors.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000030
oliver@apple.comc422ba02014-02-27 23:25:29 +000031#include "BuiltinNames.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000032#include "BytecodeGenerator.h"
33#include "CallFrame.h"
34#include "Debugger.h"
35#include "JIT.h"
36#include "JSFunction.h"
37#include "JSGlobalObject.h"
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
benjamin@webkit.org54d94f52015-02-28 03:21:37 +0000125// ------------------------------ NumberNode ----------------------------------
126
127RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
128{
129 if (dst == generator.ignoredResult())
130 return nullptr;
131 return generator.emitLoad(dst, jsValue(generator), isIntegerNode() ? SourceCodeRepresentation::Integer : SourceCodeRepresentation::Double);
132}
133
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000134// ------------------------------ RegExpNode -----------------------------------
135
136RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
137{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000138 if (dst == generator.ignoredResult())
139 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000140 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 +0000141}
142
143// ------------------------------ ThisNode -------------------------------------
144
145RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
146{
rniwa@webkit.orge8caec42015-03-31 19:42:56 +0000147 if (m_shouldAlwaysEmitTDZCheck || generator.constructorKind() == ConstructorKind::Derived)
rniwa@webkit.orgeb7ac192015-03-13 01:11:15 +0000148 generator.emitTDZCheck(generator.thisRegister());
149
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000150 if (dst == generator.ignoredResult())
151 return 0;
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000152
153 RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000154 if (generator.vm()->typeProfiler()) {
155 generator.emitProfileType(generator.thisRegister(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000156 static const unsigned thisLength = 4;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000157 generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + thisLength, -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000158 }
159 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000160}
161
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000162// ------------------------------ SuperNode -------------------------------------
163
164RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
165{
166 if (dst == generator.ignoredResult())
167 return 0;
168
169 RegisterID callee;
170 callee.setIndex(JSStack::Callee);
171
172 RefPtr<RegisterID> homeObject = generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
173 RefPtr<RegisterID> protoParent = generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
174 return generator.emitGetById(generator.finalDestination(dst), protoParent.get(), generator.propertyNames().constructor);
175}
176
177static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
178{
179 RegisterID callee;
180 callee.setIndex(JSStack::Callee);
181
182 RefPtr<RegisterID> homeObject = generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
183 return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
184}
185
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000186// ------------------------------ ResolveNode ----------------------------------
187
188bool ResolveNode::isPure(BytecodeGenerator& generator) const
189{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000190 return generator.variable(m_ident).offset().isStack();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000191}
192
193RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
194{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000195 Variable var = generator.variable(m_ident);
196 if (RegisterID* local = var.local()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000197 if (dst == generator.ignoredResult())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000198 return nullptr;
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000199 if (generator.vm()->typeProfiler()) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000200 generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000201 generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000202 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000203 return generator.moveToDestinationIfNeeded(dst, local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000204 }
205
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000206 JSTextPosition divot = m_start + m_ident.length();
207 generator.emitExpressionInfo(divot, m_start, divot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000208 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000209 RegisterID* finalDest = generator.finalDestination(dst);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000210 RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000211 if (generator.vm()->typeProfiler()) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000212 generator.emitProfileType(finalDest, var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000213 generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000214 }
215 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000216}
217
218// ------------------------------ ArrayNode ------------------------------------
219
220RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
221{
222 // FIXME: Should we put all of this code into emitNewArray?
223
224 unsigned length = 0;
225 ElementNode* firstPutElement;
226 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000227 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000228 break;
229 ++length;
230 }
231
232 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000233 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000234
oliver@apple.coma991d692011-06-14 23:39:25 +0000235 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000236 ElementNode* n = firstPutElement;
237 for (; n; n = n->next()) {
238 if (n->value()->isSpreadExpression())
239 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000240 RegisterID* value = generator.emitNode(n->value());
241 length += n->elision();
242 generator.emitPutByIndex(array.get(), length++, value);
243 }
244
245 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000246 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000247 generator.emitPutById(array.get(), generator.propertyNames().length, value);
248 }
249
250 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000251
252handleSpread:
253 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
254 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
255 {
oliver@apple.come050d642013-10-19 00:09:28 +0000256 generator.emitDirectPutByVal(array.get(), index.get(), value);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000257 generator.emitInc(index.get());
258 };
259 for (; n; n = n->next()) {
260 if (n->elision())
261 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
262 if (n->value()->isSpreadExpression()) {
263 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
264 generator.emitEnumeration(spread, spread->expression(), spreader);
265 } else {
oliver@apple.come050d642013-10-19 00:09:28 +0000266 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
oliver@apple.com72f8a822013-10-17 01:02:34 +0000267 generator.emitInc(index.get());
268 }
269 }
270
271 if (m_elision) {
272 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
273 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
274 }
275 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000276}
277
278bool ArrayNode::isSimpleArray() const
279{
280 if (m_elision || m_optional)
281 return false;
282 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
283 if (ptr->elision())
284 return false;
285 }
286 return true;
287}
288
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000289ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000290{
291 ASSERT(!m_elision && !m_optional);
292 ElementNode* ptr = m_element;
293 if (!ptr)
294 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000295 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000296 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000297 location.startOffset = startPosition;
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000298 ArgumentListNode* head = new (parserArena) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000299 ArgumentListNode* tail = head;
300 ptr = ptr->next();
301 for (; ptr; ptr = ptr->next()) {
302 ASSERT(!ptr->elision());
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000303 tail = new (parserArena) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000304 }
305 return head;
306}
307
308// ------------------------------ ObjectLiteralNode ----------------------------
309
310RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
311{
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000312 if (!m_list) {
313 if (dst == generator.ignoredResult())
314 return 0;
315 return generator.emitNewObject(generator.finalDestination(dst));
316 }
317 RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
318 generator.emitNode(newObj.get(), m_list);
319 return generator.moveToDestinationIfNeeded(dst, newObj.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000320}
321
322// ------------------------------ PropertyListNode -----------------------------
323
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000324static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
325{
326 generator.emitPutById(function, generator.propertyNames().homeObjectPrivateName, homeObject);
327}
328
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000329RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
330{
barraclough@apple.com09a55682012-01-30 18:28:39 +0000331 // Fast case: this loop just handles regular value properties.
332 PropertyListNode* p = this;
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000333 for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next)
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000334 emitPutConstantProperty(generator, dst, *p->m_node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000335
336 // Were there any get/set properties?
337 if (p) {
338 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
339 typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
340 GetterSetterMap map;
341
342 // Build a map, pairing get/set values together.
343 for (PropertyListNode* q = p; q; q = q->m_next) {
344 PropertyNode* node = q->m_node;
345 if (node->m_type == PropertyNode::Constant)
346 continue;
347
paroga@webkit.orgf990c252012-02-20 23:37:01 +0000348 GetterSetterPair pair(node, static_cast<PropertyNode*>(0));
oliver@apple.com72d38322013-10-21 19:23:24 +0000349 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +0000350 if (!result.isNewEntry)
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000351 result.iterator->value.second = node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000352 }
353
354 // Iterate over the remaining properties in the list.
355 for (; p; p = p->m_next) {
356 PropertyNode* node = p->m_node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000357
358 // Handle regular values.
359 if (node->m_type == PropertyNode::Constant) {
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000360 emitPutConstantProperty(generator, dst, *node);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000361 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000362 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000363
oliver@apple.com72d38322013-10-21 19:23:24 +0000364 RegisterID* value = generator.emitNode(node->m_assign);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000365 bool isClassProperty = node->needsSuperBinding();
366 if (isClassProperty)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000367 emitPutHomeObject(generator, value, dst);
barraclough@apple.com09a55682012-01-30 18:28:39 +0000368
369 // This is a get/set property, find its entry in the map.
370 ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
oliver@apple.com72d38322013-10-21 19:23:24 +0000371 GetterSetterMap::iterator it = map.find(node->name()->impl());
barraclough@apple.com09a55682012-01-30 18:28:39 +0000372 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000373 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000374
375 // Was this already generated as a part of its partner?
376 if (pair.second == node)
377 continue;
378
379 // Generate the paired node now.
380 RefPtr<RegisterID> getterReg;
381 RefPtr<RegisterID> setterReg;
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000382 RegisterID* secondReg = nullptr;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000383
384 if (node->m_type == PropertyNode::Getter) {
385 getterReg = value;
386 if (pair.second) {
387 ASSERT(pair.second->m_type == PropertyNode::Setter);
388 setterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000389 secondReg = setterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000390 } else {
391 setterReg = generator.newTemporary();
392 generator.emitLoad(setterReg.get(), jsUndefined());
393 }
394 } else {
395 ASSERT(node->m_type == PropertyNode::Setter);
396 setterReg = value;
397 if (pair.second) {
398 ASSERT(pair.second->m_type == PropertyNode::Getter);
399 getterReg = generator.emitNode(pair.second->m_assign);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000400 secondReg = getterReg.get();
barraclough@apple.com09a55682012-01-30 18:28:39 +0000401 } else {
402 getterReg = generator.newTemporary();
403 generator.emitLoad(getterReg.get(), jsUndefined());
404 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000405 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000406
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000407 ASSERT(!pair.second || isClassProperty == pair.second->needsSuperBinding());
408 if (isClassProperty && pair.second)
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000409 emitPutHomeObject(generator, secondReg, dst);
410
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000411 if (isClassProperty) {
412 RefPtr<RegisterID> propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node->name());
413 generator.emitCallDefineProperty(dst, propertyNameRegister.get(),
414 nullptr, getterReg.get(), setterReg.get(), BytecodeGenerator::PropertyConfigurable, m_position);
415 } else
416 generator.emitPutGetterSetter(dst, *node->name(), getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000417 }
418 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000419
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +0000420 return dst;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000421}
422
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000423void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
424{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000425 RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000426 if (node.needsSuperBinding()) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000427 emitPutHomeObject(generator, value.get(), newObj);
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +0000428
429 RefPtr<RegisterID> propertyNameRegister;
430 if (node.name())
431 propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node.name());
432 else
433 propertyNameRegister = generator.emitNode(node.m_expression);
434
435 generator.emitCallDefineProperty(newObj, propertyNameRegister.get(),
436 value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
437 return;
438 }
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000439 if (node.name()) {
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000440 generator.emitDirectPutById(newObj, *node.name(), value.get(), node.putType());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000441 return;
442 }
443 RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000444 generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
rniwa@webkit.org95698ee2015-01-22 18:07:16 +0000445}
446
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000447// ------------------------------ BracketAccessorNode --------------------------------
448
449RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
450{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000451 if (m_base->isSuperNode()) {
452 // FIXME: Should we generate the profiler info?
453 if (m_subscript->isString()) {
454 const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
455 return generator.emitGetById(generator.finalDestination(dst), emitSuperBaseForCallee(generator), id);
456 }
457 return generator.emitGetByVal(generator.finalDestination(dst), emitSuperBaseForCallee(generator), generator.emitNode(m_subscript));
458 }
459
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000460 RegisterID* ret;
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000461 RegisterID* finalDest = generator.finalDestination(dst);
akling@apple.comcbb8cfc2014-11-12 21:13:13 +0000462
463 if (m_subscript->isString()) {
464 RefPtr<RegisterID> base = generator.emitNode(m_base);
465 ret = generator.emitGetById(finalDest, base.get(), static_cast<StringNode*>(m_subscript)->value());
466 } else {
467 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
468 RegisterID* property = generator.emitNode(m_subscript);
469 ret = generator.emitGetByVal(finalDest, base.get(), property);
470 }
471
472 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
473
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000474 if (generator.vm()->typeProfiler()) {
475 generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
476 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000477 }
478 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000479}
480
481// ------------------------------ DotAccessorNode --------------------------------
482
483RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
484{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000485 RefPtr<RegisterID> base = m_base->isSuperNode() ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000486 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000487 RegisterID* finalDest = generator.finalDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000488 RegisterID* ret = generator.emitGetById(finalDest, base.get(), m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000489 if (generator.vm()->typeProfiler()) {
490 generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
491 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000492 }
493 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000494}
495
496// ------------------------------ ArgumentListNode -----------------------------
497
498RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
499{
500 ASSERT(m_expr);
501 return generator.emitNode(dst, m_expr);
502}
503
504// ------------------------------ NewExprNode ----------------------------------
505
506RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
507{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000508 ExpectedFunction expectedFunction;
509 if (m_expr->isResolveNode())
510 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
511 else
512 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000513 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000514 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000515 CallArguments callArguments(generator, m_args);
rniwa@webkit.orgfda6b5e2015-02-25 00:41:35 +0000516 generator.emitMove(callArguments.thisRegister(), func.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000517 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000518}
519
oliver@apple.com72f8a822013-10-17 01:02:34 +0000520CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000521 : m_argumentsNode(argumentsNode)
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000522 , m_padding(0)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000523{
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +0000524 if (generator.shouldEmitProfileHooks())
525 m_profileHookRegister = generator.newTemporary();
ggaren@apple.com50c5ac22011-11-14 23:16:27 +0000526
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000527 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000528 if (argumentsNode) {
529 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
530 ++argumentCountIncludingThis;
531 }
532
533 m_argv.grow(argumentCountIncludingThis);
534 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
535 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000536 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 +0000537 }
fpizlo@apple.come94ae4a2013-11-22 20:18:18 +0000538
539 while (stackOffset() % stackAlignmentRegisters()) {
540 m_argv.insert(0, generator.newTemporary());
541 m_padding++;
542 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000543}
544
545// ------------------------------ EvalFunctionCallNode ----------------------------------
546
547RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
548{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000549 Variable var = generator.variable(generator.propertyNames().eval);
550 if (RegisterID* local = var.local()) {
551 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.com58c86752013-07-25 04:02:40 +0000552 CallArguments callArguments(generator, m_args);
553 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000554 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000555 }
556
557 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000558 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000559 JSTextPosition newDivot = divotStart() + 4;
560 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000561 generator.moveToDestinationIfNeeded(
562 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000563 generator.emitResolveScope(callArguments.thisRegister(), var));
564 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000565 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000566}
567
568// ------------------------------ FunctionCallValueNode ----------------------------------
569
570RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
571{
572 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000573 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000574 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000575 if (m_expr->isSuperNode()) {
rniwa@webkit.orge6f83492015-03-13 23:01:51 +0000576 ASSERT(generator.isConstructor());
577 ASSERT(generator.constructorKind() == ConstructorKind::Derived);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000578 generator.emitMove(callArguments.thisRegister(), generator.newTarget());
579 RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
580 generator.emitMove(generator.thisRegister(), ret);
581 return ret;
582 }
oliver@apple.com64126552010-10-18 18:32:39 +0000583 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000584 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000585 if (generator.vm()->typeProfiler()) {
586 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
587 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000588 }
589 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000590}
591
592// ------------------------------ FunctionCallResolveNode ----------------------------------
593
594RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
595{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000596 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000597
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000598 Variable var = generator.variable(m_ident);
599 if (RegisterID* local = var.local()) {
600 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000601 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000602 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000603 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000604 // This passes NoExpectedFunction because we expect that if the function is in a
605 // local variable, then it's not one of our built-in constructors.
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000606 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000607 if (generator.vm()->typeProfiler()) {
608 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
609 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000610 }
611 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000612 }
613
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000614 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000615 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000616 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000617
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000618 JSTextPosition newDivot = divotStart() + m_ident.length();
619 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.coma97ccfd2015-03-02 02:08:26 +0000620 generator.moveToDestinationIfNeeded(
621 callArguments.thisRegister(),
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000622 generator.emitResolveScope(callArguments.thisRegister(), var));
623 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000624 RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000625 if (generator.vm()->typeProfiler()) {
626 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
627 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000628 }
629 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000630}
631
utatane.tea@gmail.comdefc1662015-04-20 01:45:50 +0000632// ------------------------------ BytecodeIntrinsicNode ----------------------------------
633
634RegisterID* BytecodeIntrinsicNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
635{
636 return (this->*m_emitter)(generator, dst);
637}
638
639RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putByValDirect(BytecodeGenerator& generator, RegisterID* dst)
640{
641 ArgumentListNode* node = m_args->m_listNode;
642 RefPtr<RegisterID> base = generator.emitNode(node);
643 node = node->m_next;
644 RefPtr<RegisterID> index = generator.emitNode(node);
645 node = node->m_next;
646 RefPtr<RegisterID> value = generator.emitNode(node);
647
648 ASSERT(!node->m_next);
649
650 return generator.moveToDestinationIfNeeded(dst, generator.emitDirectPutByVal(base.get(), index.get(), value.get()));
651}
652
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000653// ------------------------------ FunctionCallBracketNode ----------------------------------
654
655RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
656{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000657 bool baseIsSuper = m_base->isSuperNode();
658 RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000659 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000660 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000661 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000662 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000663 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000664 if (baseIsSuper)
665 generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
666 else
667 generator.emitMove(callArguments.thisRegister(), base.get());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000668 RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000669 if (generator.vm()->typeProfiler()) {
670 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
671 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000672 }
673 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000674}
675
676// ------------------------------ FunctionCallDotNode ----------------------------------
677
678RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
679{
680 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000681 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000682 CallArguments callArguments(generator, m_args);
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000683 bool baseIsSuper = m_base->isSuperNode();
684 if (baseIsSuper)
685 generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
686 else
687 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000688 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +0000689 generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000690 RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000691 if (generator.vm()->typeProfiler()) {
692 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
693 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000694 }
695 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000696}
697
698RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
699{
700 RefPtr<Label> realCall = generator.newLabel();
701 RefPtr<Label> end = generator.newLabel();
702 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000703 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000704 RefPtr<RegisterID> function;
oliver@apple.comba848d12014-02-12 17:14:23 +0000705 bool emitCallCheck = !generator.isBuiltinFunction();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000706 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000707 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000708 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000709 }
710 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000711 {
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000712 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
713 RefPtr<RegisterID> profileHookRegister;
714 if (generator.shouldEmitProfileHooks())
715 profileHookRegister = generator.newTemporary();
716 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
717 ExpressionNode* subject = spread->expression();
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000718 RefPtr<RegisterID> argumentsRegister;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000719 argumentsRegister = generator.emitNode(subject);
720 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
721 RefPtr<RegisterID> thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000722 generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
723 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000724 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000725 m_args->m_listNode = m_args->m_listNode->m_next;
oliver@apple.comd04e0a02014-02-01 01:37:59 +0000726
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000727 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
728 CallArguments callArguments(generator, m_args);
729 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000730 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000731 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000732 } else {
733 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
734 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000735 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000736 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000737 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000738 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000739 if (emitCallCheck) {
740 generator.emitJump(end.get());
741 generator.emitLabel(realCall.get());
742 {
743 CallArguments callArguments(generator, m_args);
744 generator.emitMove(callArguments.thisRegister(), base.get());
745 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
746 }
747 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000748 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000749 if (generator.vm()->typeProfiler()) {
750 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
751 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000752 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000753 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000754}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000755
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000756static bool areTrivialApplyArguments(ArgumentsNode* args)
757{
758 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
759 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
760}
761
762RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
763{
764 // A few simple cases can be trivially handled as ordinary function calls.
765 // function.apply(), function.apply(arg) -> identical to function.call
766 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
767 bool mayBeCall = areTrivialApplyArguments(m_args);
768
769 RefPtr<Label> realCall = generator.newLabel();
770 RefPtr<Label> end = generator.newLabel();
771 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000772 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000773 RefPtr<RegisterID> function;
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000774 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000775 bool emitCallCheck = !generator.isBuiltinFunction();
776 if (emitCallCheck) {
oliver@apple.comc422ba02014-02-27 23:25:29 +0000777 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
oliver@apple.comba848d12014-02-12 17:14:23 +0000778 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
779 }
780 if (mayBeCall) {
781 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
782 ArgumentListNode* oldList = m_args->m_listNode;
oliver@apple.com0989d9b2014-02-26 20:40:46 +0000783 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
784 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
785 RefPtr<RegisterID> profileHookRegister;
786 if (generator.shouldEmitProfileHooks())
787 profileHookRegister = generator.newTemporary();
788 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
789 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
790 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
791 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
792
793 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
794 {
795 RefPtr<Label> haveThis = generator.newLabel();
796 RefPtr<Label> end = generator.newLabel();
797 RefPtr<RegisterID> compareResult = generator.newTemporary();
798 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
799 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
800 generator.emitMove(thisRegister.get(), value);
801 generator.emitLoad(index.get(), jsNumber(1));
802 generator.emitJump(end.get());
803 generator.emitLabel(haveThis.get());
804 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
805 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
806 generator.emitMove(argumentsRegister.get(), value);
807 generator.emitLoad(index.get(), jsNumber(2));
808 generator.emitLabel(end.get());
809 };
810 generator.emitEnumeration(this, spread->expression(), extractor);
811 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
812 } else if (m_args->m_listNode->m_next) {
oliver@apple.comba848d12014-02-12 17:14:23 +0000813 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
814 ASSERT(!m_args->m_listNode->m_next->m_next);
ggaren@apple.comc0ccae02014-12-03 23:23:56 +0000815 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.parserArena(), 0, 0);
oliver@apple.comfca9a922014-01-31 21:34:38 +0000816 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
817 CallArguments callArguments(generator, m_args);
oliver@apple.comba848d12014-02-12 17:14:23 +0000818 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
819 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
820 } else {
821 m_args->m_listNode = m_args->m_listNode->m_next;
822 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
823 CallArguments callArguments(generator, m_args);
824 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000825 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000826 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000827 m_args->m_listNode = oldList;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000828 } else {
ggaren@apple.combcf06d32012-01-12 00:14:42 +0000829 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
oliver@apple.comba848d12014-02-12 17:14:23 +0000830 CallArguments callArguments(generator, m_args);
831 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
832 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000833 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000834 } else {
835 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
836 RefPtr<RegisterID> profileHookRegister;
837 if (generator.shouldEmitProfileHooks())
838 profileHookRegister = generator.newTemporary();
839 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
840 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
841 RefPtr<RegisterID> argsRegister;
842 ArgumentListNode* args = m_args->m_listNode->m_next;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000843 argsRegister = generator.emitNode(args->m_expr);
oliver@apple.comba848d12014-02-12 17:14:23 +0000844
845 // Function.prototype.apply ignores extra arguments, but we still
846 // need to evaluate them for side effects.
847 while ((args = args->m_next))
848 generator.emitNode(args->m_expr);
849
oliver@apple.com2f5c83b2014-02-25 06:59:38 +0000850 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 +0000851 }
oliver@apple.comba848d12014-02-12 17:14:23 +0000852 if (emitCallCheck) {
853 generator.emitJump(end.get());
854 generator.emitLabel(realCall.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000855 CallArguments callArguments(generator, m_args);
856 generator.emitMove(callArguments.thisRegister(), base.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000857 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
oliver@apple.comba848d12014-02-12 17:14:23 +0000858 generator.emitLabel(end.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000859 }
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000860 if (generator.vm()->typeProfiler()) {
861 generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
862 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000863 }
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000864 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000865}
866
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000867// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000868
ggaren@apple.comf3036112013-04-27 23:14:04 +0000869static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000870{
ggaren@apple.comf3036112013-04-27 23:14:04 +0000871 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000872}
873
874static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
875{
ggaren@apple.comf3036112013-04-27 23:14:04 +0000876 if (dst == srcDst)
877 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
878 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
879 emitIncOrDec(generator, srcDst, oper);
880 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000881}
882
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000883RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000884{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000885 if (dst == generator.ignoredResult())
886 return PrefixNode::emitResolve(generator, dst);
887
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000888 ASSERT(m_expr->isResolveNode());
889 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
890 const Identifier& ident = resolve->identifier();
891
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000892 Variable var = generator.variable(ident);
893 if (RegisterID* local = var.local()) {
894 RefPtr<RegisterID> localReg = local;
895 if (var.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +0000896 generator.emitReadOnlyExceptionIfNeeded();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000897 localReg = generator.emitMove(generator.tempDestination(dst), local);
oliver@apple.comf129dfb2014-10-02 20:35:58 +0000898 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000899 RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
900 ASSERT(dst != localReg);
901 RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000902 generator.emitToNumber(tempDst.get(), localReg.get());
903 generator.emitMove(tempDstSrc.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000904 emitIncOrDec(generator, tempDstSrc.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000905 generator.emitMove(localReg.get(), tempDstSrc.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000906 if (generator.vm()->typeProfiler())
907 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +0000908 return tempDst.get();
909 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +0000910 return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000911 }
oliver@apple.com75f804e2013-03-07 00:25:20 +0000912
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000913 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000914 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
915 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000916 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000917 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000918 if (generator.vm()->typeProfiler()) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000919 generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000920 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +0000921 }
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000922
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000923 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000924}
925
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000926RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000927{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000928 if (dst == generator.ignoredResult())
929 return PrefixNode::emitBracket(generator, dst);
930
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000931 ASSERT(m_expr->isBracketAccessorNode());
932 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
933 ExpressionNode* baseNode = bracketAccessor->base();
934 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000935
barraclough@apple.come3aa3f52012-09-06 00:55:46 +0000936 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000937 RefPtr<RegisterID> property = generator.emitNode(subscript);
938
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000939 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000940 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000941 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000942 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000943 generator.emitPutByVal(base.get(), property.get(), value.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000944 if (generator.vm()->typeProfiler()) {
945 generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
946 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000947 }
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000948 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000949}
950
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000951RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000952{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000953 if (dst == generator.ignoredResult())
954 return PrefixNode::emitDot(generator, dst);
955
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000956 ASSERT(m_expr->isDotAccessorNode());
957 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
958 ExpressionNode* baseNode = dotAccessor->base();
959 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000960
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000961 RefPtr<RegisterID> base = generator.emitNode(baseNode);
962
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000963 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000964 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000965 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000966 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000967 generator.emitPutById(base.get(), ident, value.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +0000968 if (generator.vm()->typeProfiler()) {
969 generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
970 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +0000971 }
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000972 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000973}
974
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000975RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000976{
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000977 if (m_expr->isResolveNode())
978 return emitResolve(generator, dst);
979
980 if (m_expr->isBracketAccessorNode())
981 return emitBracket(generator, dst);
982
983 if (m_expr->isDotAccessorNode())
984 return emitDot(generator, dst);
985
barraclough@apple.com4920ae92010-11-12 03:06:07 +0000986 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +0000987 ? ASCIILiteral("Postfix ++ operator applied to value that is not a reference.")
988 : ASCIILiteral("Postfix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000989}
990
991// ------------------------------ DeleteResolveNode -----------------------------------
992
993RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
994{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000995 Variable var = generator.variable(m_ident);
996 if (var.local())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000997 return generator.emitLoad(generator.finalDestination(dst), false);
998
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000999 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001000 RefPtr<RegisterID> base = generator.emitResolveScope(dst, var);
oliver@apple.com58c86752013-07-25 04:02:40 +00001001 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001002}
1003
1004// ------------------------------ DeleteBracketNode -----------------------------------
1005
1006RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1007{
1008 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001009 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001010
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001011 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001012 if (m_base->isSuperNode())
1013 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001014 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001015}
1016
1017// ------------------------------ DeleteDotNode -----------------------------------
1018
1019RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1020{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001021 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001022
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001023 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00001024 if (m_base->isSuperNode())
1025 return emitThrowReferenceError(generator, "Cannot delete a super property");
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001026 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001027}
1028
1029// ------------------------------ DeleteValueNode -----------------------------------
1030
1031RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1032{
1033 generator.emitNode(generator.ignoredResult(), m_expr);
1034
1035 // delete on a non-location expression ignores the value and returns true
1036 return generator.emitLoad(generator.finalDestination(dst), true);
1037}
1038
1039// ------------------------------ VoidNode -------------------------------------
1040
1041RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1042{
1043 if (dst == generator.ignoredResult()) {
1044 generator.emitNode(generator.ignoredResult(), m_expr);
1045 return 0;
1046 }
1047 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1048 return generator.emitLoad(dst, jsUndefined());
1049}
1050
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001051// ------------------------------ TypeOfResolveNode -----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001052
1053RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1054{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001055 Variable var = generator.variable(m_ident);
1056 if (RegisterID* local = var.local()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001057 if (dst == generator.ignoredResult())
1058 return 0;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001059 return generator.emitTypeOf(generator.finalDestination(dst), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001060 }
1061
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001062 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1063 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001064 if (dst == generator.ignoredResult())
1065 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001066 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001067}
1068
1069// ------------------------------ TypeOfValueNode -----------------------------------
1070
1071RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1072{
1073 if (dst == generator.ignoredResult()) {
1074 generator.emitNode(generator.ignoredResult(), m_expr);
1075 return 0;
1076 }
1077 RefPtr<RegisterID> src = generator.emitNode(m_expr);
1078 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
1079}
1080
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001081// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001082
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001083RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001084{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001085 ASSERT(m_expr->isResolveNode());
1086 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
1087 const Identifier& ident = resolve->identifier();
1088
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001089 Variable var = generator.variable(ident);
1090 if (RegisterID* local = var.local()) {
1091 RefPtr<RegisterID> localReg = local;
1092 if (var.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001093 generator.emitReadOnlyExceptionIfNeeded();
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001094 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001095 } else if (generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001096 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001097 generator.emitMove(tempDst.get(), localReg.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001098 emitIncOrDec(generator, tempDst.get(), m_operator);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001099 generator.emitMove(localReg.get(), tempDst.get());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001100 if (generator.vm()->typeProfiler())
1101 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001102 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1103 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001104 emitIncOrDec(generator, localReg.get(), m_operator);
1105 return generator.moveToDestinationIfNeeded(dst, localReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001106 }
1107
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001108 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001109 RefPtr<RegisterID> scope = generator.emitResolveScope(dst, var);
1110 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
oliver@apple.com58c86752013-07-25 04:02:40 +00001111 emitIncOrDec(generator, value.get(), m_operator);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001112 generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001113 if (generator.vm()->typeProfiler()) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001114 generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001115 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001116 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001117 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001118}
1119
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001120RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001121{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001122 ASSERT(m_expr->isBracketAccessorNode());
1123 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
1124 ExpressionNode* baseNode = bracketAccessor->base();
1125 ExpressionNode* subscript = bracketAccessor->subscript();
1126
barraclough@apple.come3aa3f52012-09-06 00:55:46 +00001127 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001128 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001129 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1130
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001131 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001132 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +00001133 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001134 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001135 generator.emitPutByVal(base.get(), property.get(), value);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001136 if (generator.vm()->typeProfiler()) {
1137 generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1138 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001139 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001140 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1141}
1142
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001143RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001144{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001145 ASSERT(m_expr->isDotAccessorNode());
1146 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
1147 ExpressionNode* baseNode = dotAccessor->base();
1148 const Identifier& ident = dotAccessor->identifier();
1149
1150 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001151 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
1152
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001153 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001154 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +00001155 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001156 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001157 generator.emitPutById(base.get(), ident, value);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001158 if (generator.vm()->typeProfiler()) {
1159 generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1160 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001161 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001162 return generator.moveToDestinationIfNeeded(dst, propDst.get());
1163}
1164
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001165RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001166{
barraclough@apple.comff7867a2012-09-05 23:00:29 +00001167 if (m_expr->isResolveNode())
1168 return emitResolve(generator, dst);
1169
1170 if (m_expr->isBracketAccessorNode())
1171 return emitBracket(generator, dst);
1172
1173 if (m_expr->isDotAccessorNode())
1174 return emitDot(generator, dst);
1175
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001176 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001177 ? ASCIILiteral("Prefix ++ operator applied to value that is not a reference.")
1178 : ASCIILiteral("Prefix -- operator applied to value that is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001179}
1180
1181// ------------------------------ Unary Operation Nodes -----------------------------------
1182
1183RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1184{
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001185 RefPtr<RegisterID> src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001186 generator.emitExpressionInfo(position(), position(), position());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001187 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001188}
1189
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001190// ------------------------------ BitwiseNotNode -----------------------------------
1191
1192RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1193{
1194 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001195 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1196 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +00001197}
1198
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001199// ------------------------------ LogicalNotNode -----------------------------------
1200
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001201void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001202{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001203 // reverse the true and false targets
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001204 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001205}
1206
1207
1208// ------------------------------ Binary Operation Nodes -----------------------------------
1209
1210// BinaryOpNode::emitStrcat:
1211//
1212// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1213// more values, where we can determine a set of separate op_add operations would be operating on
1214// string values.
1215//
1216// This function expects to be operating on a graph of AST nodes looking something like this:
1217//
1218// (a)... (b)
1219// \ /
1220// (+) (c)
1221// \ /
1222// [d] ((+))
1223// \ /
1224// [+=]
1225//
1226// The assignment operation is optional, if it exists the register holding the value on the
1227// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1228//
1229// The method should be called on the node at the root of the tree of regular binary add
1230// operations (marked in the diagram with a double set of parentheses). This node must
1231// be performing a string concatenation (determined by statically detecting that at least
1232// one child must be a string).
1233//
1234// Since the minimum number of values being concatenated together is expected to be 3, if
1235// a lhs to a concatenating assignment is not provided then the root add should have at
1236// least one left child that is also an add that can be determined to be operating on strings.
1237//
1238RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1239{
1240 ASSERT(isAdd());
1241 ASSERT(resultDescriptor().definitelyIsString());
1242
1243 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1244 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1245 // added first, and the leftmost child is never added, so the vector produced for the
1246 // example above will be [ c, b ].
1247 Vector<ExpressionNode*, 16> reverseExpressionList;
1248 reverseExpressionList.append(m_expr2);
1249
1250 // Examine the left child of the add. So long as this is a string add, add its right-child
1251 // to the list, and keep processing along the left fork.
1252 ExpressionNode* leftMostAddChild = m_expr1;
1253 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1254 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1255 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1256 }
1257
1258 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1259
1260 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1261 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1262 // op_strcat node handle its conversion if required).
1263 if (lhs)
1264 temporaryRegisters.append(generator.newTemporary());
1265
1266 // Emit code for the leftmost node ((a) in the example).
1267 temporaryRegisters.append(generator.newTemporary());
1268 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1269 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1270
1271 // Note on ordering of conversions:
1272 //
1273 // We maintain the same ordering of conversions as we would see if the concatenations
1274 // was performed as a sequence of adds (otherwise this optimization could change
1275 // behaviour should an object have been provided a valueOf or toString method).
1276 //
1277 // Considering the above example, the sequnce of execution is:
1278 // * evaluate operand (a)
1279 // * evaluate operand (b)
1280 // * convert (a) to primitive <- (this would be triggered by the first add)
1281 // * convert (b) to primitive <- (ditto)
1282 // * evaluate operand (c)
1283 // * convert (c) to primitive <- (this would be triggered by the second add)
1284 // And optionally, if there is an assignment:
1285 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1286 //
1287 // As such we do not plant an op to convert the leftmost child now. Instead, use
1288 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1289 // once the second node has been generated. However, if the leftmost child is an
1290 // immediate we can trivially determine that no conversion will be required.
1291 // If this is the case
1292 if (leftMostAddChild->isString())
1293 leftMostAddChildTempRegister = 0;
1294
1295 while (reverseExpressionList.size()) {
1296 ExpressionNode* node = reverseExpressionList.last();
1297 reverseExpressionList.removeLast();
1298
1299 // Emit the code for the current node.
1300 temporaryRegisters.append(generator.newTemporary());
1301 generator.emitNode(temporaryRegisters.last().get(), node);
1302
1303 // On the first iteration of this loop, when we first reach this point we have just
1304 // generated the second node, which means it is time to convert the leftmost operand.
1305 if (leftMostAddChildTempRegister) {
1306 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1307 leftMostAddChildTempRegister = 0; // Only do this once.
1308 }
1309 // Plant a conversion for this node, if necessary.
1310 if (!node->isString())
1311 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1312 }
1313 ASSERT(temporaryRegisters.size() >= 3);
1314
1315 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1316 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1317 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001318 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001319 // If there is an assignment convert the lhs now. This will also copy lhs to
1320 // the temporary register we allocated for it.
1321 if (lhs)
1322 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1323
1324 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1325}
1326
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001327void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1328{
1329 TriState branchCondition;
1330 ExpressionNode* branchExpression;
1331 tryFoldToBranch(generator, branchCondition, branchExpression);
1332
1333 if (branchCondition == MixedTriState)
1334 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1335 else if (branchCondition == TrueTriState)
1336 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1337 else
1338 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1339}
1340
1341static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1342{
1343 ResultType expressionType = branchExpression->resultDescriptor();
1344
1345 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1346 return true;
1347 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1348 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1349 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1350 return true;
1351
1352 return false;
1353}
1354
1355void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1356{
1357 branchCondition = MixedTriState;
1358 branchExpression = 0;
1359
1360 ConstantNode* constant = 0;
1361 if (m_expr1->isConstant()) {
1362 constant = static_cast<ConstantNode*>(m_expr1);
1363 branchExpression = m_expr2;
1364 } else if (m_expr2->isConstant()) {
1365 constant = static_cast<ConstantNode*>(m_expr2);
1366 branchExpression = m_expr1;
1367 }
1368
1369 if (!constant)
1370 return;
1371 ASSERT(branchExpression);
1372
1373 OpcodeID opcodeID = this->opcodeID();
1374 JSValue value = constant->jsValue(generator);
1375 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1376 if (!canFoldToBranch)
1377 return;
1378
1379 if (opcodeID == op_eq || opcodeID == op_stricteq)
1380 branchCondition = triState(value.pureToBoolean());
1381 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1382 branchCondition = triState(!value.pureToBoolean());
1383}
1384
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001385RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1386{
1387 OpcodeID opcodeID = this->opcodeID();
1388
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001389 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001390 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001391 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001392 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001393
1394 if (opcodeID == op_neq) {
1395 if (m_expr1->isNull() || m_expr2->isNull()) {
1396 RefPtr<RegisterID> src = generator.tempDestination(dst);
1397 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1398 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1399 }
1400 }
1401
oliver@apple.comece74042012-12-01 00:50:39 +00001402 ExpressionNode* left = m_expr1;
1403 ExpressionNode* right = m_expr2;
1404 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1405 if (left->isString())
1406 std::swap(left, right);
1407 }
1408
1409 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
rniwa@webkit.org679fb98f2015-01-22 02:06:33 +00001410 bool wasTypeof = generator.lastOpcodeID() == op_typeof;
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001411 RefPtr<RegisterID> src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001412 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001413 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001414 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1415 if (opcodeID == op_neq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001416 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001417 else if (opcodeID == op_nstricteq)
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001418 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001419 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001420 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001421 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1422 }
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001423 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001424 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1425 return generator.emitUnaryOp(op_unsigned, result, result);
1426 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001427}
1428
1429RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1430{
1431 if (m_expr1->isNull() || m_expr2->isNull()) {
1432 RefPtr<RegisterID> src = generator.tempDestination(dst);
1433 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1434 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1435 }
1436
oliver@apple.comece74042012-12-01 00:50:39 +00001437 ExpressionNode* left = m_expr1;
1438 ExpressionNode* right = m_expr2;
1439 if (left->isString())
1440 std::swap(left, right);
1441
1442 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001443 RefPtr<RegisterID> src2 = generator.emitNode(right);
1444 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001445}
1446
1447RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1448{
oliver@apple.comece74042012-12-01 00:50:39 +00001449 ExpressionNode* left = m_expr1;
1450 ExpressionNode* right = m_expr2;
1451 if (left->isString())
1452 std::swap(left, right);
1453
1454 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001455 RefPtr<RegisterID> src2 = generator.emitNode(right);
1456 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001457}
1458
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001459RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1460{
1461 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001462 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001463 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001464 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001465}
1466
1467RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1468{
1469 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1470 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001471 RefPtr<RegisterID> prototype = generator.newTemporary();
1472 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1473 RefPtr<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001474
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001475 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001476 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001477
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001478 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00001479 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001480
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001481 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com094dbd92012-09-22 01:18:54 +00001482 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001483 generator.emitLabel(target.get());
1484 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001485}
1486
1487// ------------------------------ LogicalOpNode ----------------------------
1488
1489RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1490{
1491 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1492 RefPtr<Label> target = generator.newLabel();
1493
1494 generator.emitNode(temp.get(), m_expr1);
1495 if (m_operator == OpLogicalAnd)
1496 generator.emitJumpIfFalse(temp.get(), target.get());
1497 else
1498 generator.emitJumpIfTrue(temp.get(), target.get());
1499 generator.emitNode(temp.get(), m_expr2);
1500 generator.emitLabel(target.get());
1501
1502 return generator.moveToDestinationIfNeeded(dst, temp.get());
1503}
1504
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001505void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001506{
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001507 RefPtr<Label> afterExpr1 = generator.newLabel();
1508 if (m_operator == OpLogicalAnd)
1509 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1510 else
1511 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1512 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001513
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001514 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001515}
1516
1517// ------------------------------ ConditionalNode ------------------------------
1518
1519RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1520{
1521 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1522 RefPtr<Label> beforeElse = generator.newLabel();
1523 RefPtr<Label> afterElse = generator.newLabel();
1524
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001525 RefPtr<Label> beforeThen = generator.newLabel();
1526 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1527 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001528
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001529 generator.emitProfileControlFlow(m_expr1->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001530 generator.emitNode(newDst.get(), m_expr1);
1531 generator.emitJump(afterElse.get());
1532
1533 generator.emitLabel(beforeElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001534 generator.emitProfileControlFlow(m_expr1->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001535 generator.emitNode(newDst.get(), m_expr2);
1536
1537 generator.emitLabel(afterElse.get());
1538
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001539 generator.emitProfileControlFlow(m_expr2->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001540
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001541 return newDst.get();
1542}
1543
1544// ------------------------------ ReadModifyResolveNode -----------------------------------
1545
1546// FIXME: should this be moved to be a method on BytecodeGenerator?
1547static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1548{
1549 OpcodeID opcodeID;
1550 switch (oper) {
1551 case OpMultEq:
1552 opcodeID = op_mul;
1553 break;
1554 case OpDivEq:
1555 opcodeID = op_div;
1556 break;
1557 case OpPlusEq:
1558 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1559 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1560 opcodeID = op_add;
1561 break;
1562 case OpMinusEq:
1563 opcodeID = op_sub;
1564 break;
1565 case OpLShift:
1566 opcodeID = op_lshift;
1567 break;
1568 case OpRShift:
1569 opcodeID = op_rshift;
1570 break;
1571 case OpURShift:
1572 opcodeID = op_urshift;
1573 break;
1574 case OpAndEq:
1575 opcodeID = op_bitand;
1576 break;
1577 case OpXOrEq:
1578 opcodeID = op_bitxor;
1579 break;
1580 case OpOrEq:
1581 opcodeID = op_bitor;
1582 break;
1583 case OpModEq:
1584 opcodeID = op_mod;
1585 break;
1586 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001587 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001588 return dst;
1589 }
1590
1591 RegisterID* src2 = generator.emitNode(m_right);
1592
1593 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1594 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1595 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001596 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
fpizlo@apple.com9089acb2013-12-14 06:33:42 +00001597 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1598 if (oper == OpURShift)
1599 return generator.emitUnaryOp(op_unsigned, result, result);
1600 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001601}
1602
1603RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1604{
fpizlo@apple.com3378c482014-07-27 23:14:40 +00001605 JSTextPosition newDivot = divotStart() + m_ident.length();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001606 Variable var = generator.variable(m_ident);
1607 if (RegisterID* local = var.local()) {
1608 if (var.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001609 generator.emitReadOnlyExceptionIfNeeded();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001610 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
ggaren@apple.com6e309822012-09-05 21:44:43 +00001611 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001612
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001613 if (generator.vm()->typeProfiler()
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001614 || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001615 RefPtr<RegisterID> result = generator.newTemporary();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001616 generator.emitMove(result.get(), local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001617 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001618 generator.emitMove(local, result.get());
1619 generator.invalidateForInContextForLocal(local);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001620 if (generator.vm()->typeProfiler())
1621 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001622 return generator.moveToDestinationIfNeeded(dst, result.get());
1623 }
1624
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001625 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1626 generator.invalidateForInContextForLocal(local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001627 return generator.moveToDestinationIfNeeded(dst, result);
1628 }
1629
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001630 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001631 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1632 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
oliver@apple.com58c86752013-07-25 04:02:40 +00001633 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001634 RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001635 if (generator.vm()->typeProfiler()) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001636 generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001637 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001638 }
1639 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001640}
1641
1642// ------------------------------ AssignResolveNode -----------------------------------
1643
1644RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1645{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001646 Variable var = generator.variable(m_ident);
1647 if (RegisterID* local = var.local()) {
1648 if (var.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001649 generator.emitReadOnlyExceptionIfNeeded();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001650 return generator.emitNode(dst, m_right);
ggaren@apple.com6e309822012-09-05 21:44:43 +00001651 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001652 if (var.isSpecial() || generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001653 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1654 generator.emitNode(tempDst.get(), m_right);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001655 generator.emitMove(local, tempDst.get());
1656 generator.invalidateForInContextForLocal(local);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001657 if (generator.vm()->typeProfiler())
1658 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001659 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1660 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001661 RegisterID* result = generator.emitNode(local, m_right);
1662 generator.invalidateForInContextForLocal(local);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001663 return generator.moveToDestinationIfNeeded(dst, result);
1664 }
1665
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001666 if (generator.isStrictMode())
1667 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001668 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001669 if (dst == generator.ignoredResult())
1670 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001671 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001672 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001673 RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001674 if (generator.vm()->typeProfiler()) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001675 generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001676 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001677 }
1678 return returnResult;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001679}
1680
1681// ------------------------------ AssignDotNode -----------------------------------
1682
1683RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1684{
1685 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1686 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001687 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001688 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001689 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001690 generator.emitPutById(base.get(), m_ident, forwardResult);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001691 if (generator.vm()->typeProfiler()) {
1692 generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1693 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001694 }
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001695 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001696}
1697
1698// ------------------------------ ReadModifyDotNode -----------------------------------
1699
1700RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1701{
1702 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1703
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001704 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001705 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001706 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 +00001707
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001708 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001709 RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001710 if (generator.vm()->typeProfiler()) {
1711 generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1712 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001713 }
1714 return ret;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001715}
1716
1717// ------------------------------ AssignErrorNode -----------------------------------
1718
1719RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1720{
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001721 return emitThrowReferenceError(generator, ASCIILiteral("Left side of assignment is not a reference."));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001722}
1723
1724// ------------------------------ AssignBracketNode -----------------------------------
1725
1726RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1727{
1728 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1729 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1730 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001731 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001732
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001733 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com3e6693a2015-01-13 19:42:36 +00001734 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
akling@apple.come09d0422014-11-13 19:18:43 +00001735
1736 if (m_subscript->isString())
1737 generator.emitPutById(base.get(), static_cast<StringNode*>(m_subscript)->value(), forwardResult);
1738 else
1739 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1740
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001741 if (generator.vm()->typeProfiler()) {
1742 generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1743 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001744 }
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001745 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001746}
1747
1748// ------------------------------ ReadModifyBracketNode -----------------------------------
1749
1750RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1751{
1752 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1753 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1754
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001755 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001756 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
bfulgham@apple.com9c9b8a12014-06-24 19:49:25 +00001757 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 +00001758
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001759 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001760 generator.emitPutByVal(base.get(), property.get(), updatedValue);
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001761 if (generator.vm()->typeProfiler()) {
1762 generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
1763 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001764 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001765
1766 return updatedValue;
1767}
1768
1769// ------------------------------ CommaNode ------------------------------------
1770
1771RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1772{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001773 CommaNode* node = this;
1774 for (; node && node->next(); node = node->next())
1775 generator.emitNode(generator.ignoredResult(), node->m_expr);
1776 return generator.emitNode(dst, node->m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001777}
1778
1779// ------------------------------ ConstDeclNode ------------------------------------
1780
1781RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1782{
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001783 // FIXME: This code does not match the behavior of const in Firefox.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001784 Variable var = generator.variable(m_ident);
1785 if (RegisterID* local = var.local()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001786 if (!m_init)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001787 return local;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001788
fpizlo@apple.com3378c482014-07-27 23:14:40 +00001789 // FIXME: Maybe call emitExpressionInfo here.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001790 if (var.isSpecial() || generator.vm()->typeProfiler()) {
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001791 RefPtr<RegisterID> tempDst = generator.newTemporary();
1792 generator.emitNode(tempDst.get(), m_init);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001793 return generator.emitMove(local, tempDst.get());
fpizlo@apple.com0309686b2013-12-02 19:49:43 +00001794 }
1795
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001796 return generator.emitNode(local, m_init);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001797 }
1798
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001799 RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1800
oliver@apple.com75f804e2013-03-07 00:25:20 +00001801 if (generator.codeType() == GlobalCode)
1802 return generator.emitInitGlobalConst(m_ident, value.get());
1803
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001804 if (generator.codeType() != EvalCode) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001805 // Do a special kind of resolution. If anything fails, then don't perform the assignment. This is
1806 // pretty shady - particularly how negligent it is with inteleaving scopes - but it's the
1807 // behavior that JSC has had for a long time.
1808
fpizlo@apple.com9cb84382015-03-26 04:35:31 +00001809 ASSERT(generator.codeType() == FunctionCode);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001810
1811 var = generator.variablePerSymbolTable(m_ident);
1812 if (!var.isResolved())
1813 return value.get();
1814
1815 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), var);
1816 return generator.emitPutToScope(scope.get(), var, value.get(), DoNotThrowIfNotFound);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001817 }
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001818
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001819 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001820 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1821 return generator.emitPutToScope(scope.get(), var, value.get(), DoNotThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001822}
1823
1824RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1825{
1826 RegisterID* result = 0;
1827 for (ConstDeclNode* n = this; n; n = n->m_next)
1828 result = n->emitCodeSingle(generator);
1829
1830 return result;
1831}
1832
1833// ------------------------------ ConstStatementNode -----------------------------
1834
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001835void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001836{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001837 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001838 generator.emitNode(m_next);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001839}
1840
1841// ------------------------------ SourceElements -------------------------------
1842
1843
1844inline StatementNode* SourceElements::lastStatement() const
1845{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001846 return m_tail;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001847}
1848
1849inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1850{
ggaren@apple.com86cb7be2014-12-09 01:53:53 +00001851 for (StatementNode* statement = m_head; statement; statement = statement->next())
1852 generator.emitNode(dst, statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001853}
1854
1855// ------------------------------ BlockNode ------------------------------------
1856
1857inline StatementNode* BlockNode::lastStatement() const
1858{
1859 return m_statements ? m_statements->lastStatement() : 0;
1860}
1861
ggaren@apple.comddc6f102015-03-20 20:12:10 +00001862StatementNode* BlockNode::singleStatement() const
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00001863{
1864 return m_statements ? m_statements->singleStatement() : 0;
1865}
1866
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001867void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001868{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001869 if (!m_statements)
1870 return;
1871 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001872}
1873
1874// ------------------------------ EmptyStatementNode ---------------------------
1875
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001876void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001877{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001878 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001879}
1880
1881// ------------------------------ DebuggerStatementNode ---------------------------
1882
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001883void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001884{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001885 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001886}
1887
1888// ------------------------------ ExprStatementNode ----------------------------
1889
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001890void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001891{
1892 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001893 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001894 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001895}
1896
1897// ------------------------------ VarStatementNode ----------------------------
1898
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001899void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001900{
1901 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001902 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001903 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001904}
1905
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001906// ------------------------------ EmptyVarExpression ----------------------------
1907
1908RegisterID* EmptyVarExpression::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1909{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001910 if (!generator.vm()->typeProfiler())
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001911 return nullptr;
1912
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001913 Variable var = generator.variable(m_ident);
1914 if (RegisterID* local = var.local())
1915 generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001916 else {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001917 RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
1918 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
1919 generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001920 }
1921
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001922 generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
commit-queue@webkit.org200ce5b2014-08-18 19:11:41 +00001923
1924 // It's safe to return null here because this node will always be a child node of VarStatementNode which ignores our return value.
1925 return nullptr;
1926}
1927
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001928// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001929
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001930static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001931{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001932 if (statementNode->isBlock())
1933 return static_cast<BlockNode*>(statementNode)->singleStatement();
1934 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001935}
1936
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001937bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
1938 Label*& trueTarget, FallThroughMode& fallThroughMode)
1939{
1940 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
1941 if (!singleStatement)
1942 return false;
1943
1944 if (singleStatement->isBreak()) {
1945 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
1946 Label* target = breakNode->trivialTarget(generator);
1947 if (!target)
1948 return false;
1949 trueTarget = target;
1950 fallThroughMode = FallThroughMeansFalse;
1951 return true;
1952 }
1953
1954 if (singleStatement->isContinue()) {
1955 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
1956 Label* target = continueNode->trivialTarget(generator);
1957 if (!target)
1958 return false;
1959 trueTarget = target;
1960 fallThroughMode = FallThroughMeansFalse;
1961 return true;
1962 }
1963
1964 return false;
1965}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001966
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001967void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001968{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001969 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org5fb80322014-04-15 17:46:42 +00001970
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001971 RefPtr<Label> beforeThen = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001972 RefPtr<Label> beforeElse = generator.newLabel();
1973 RefPtr<Label> afterElse = generator.newLabel();
1974
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001975 Label* trueTarget = beforeThen.get();
1976 Label* falseTarget = beforeElse.get();
1977 FallThroughMode fallThroughMode = FallThroughMeansTrue;
1978 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
1979
1980 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001981 generator.emitLabel(beforeThen.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001982 generator.emitProfileControlFlow(m_ifBlock->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001983
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001984 if (!didFoldIfBlock) {
1985 generator.emitNode(dst, m_ifBlock);
1986 if (m_elseBlock)
1987 generator.emitJump(afterElse.get());
1988 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001989
1990 generator.emitLabel(beforeElse.get());
1991
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001992 if (m_elseBlock) {
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001993 generator.emitProfileControlFlow(m_ifBlock->endOffset() + (m_ifBlock->isBlock() ? 1 : 0));
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001994 generator.emitNode(dst, m_elseBlock);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00001995 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001996
1997 generator.emitLabel(afterElse.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00001998 StatementNode* endingBlock = m_elseBlock ? m_elseBlock : m_ifBlock;
1999 generator.emitProfileControlFlow(endingBlock->endOffset() + (endingBlock->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002000}
2001
2002// ------------------------------ DoWhileNode ----------------------------------
2003
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002004void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002005{
oliver@apple.com6a976452013-03-11 21:02:39 +00002006 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002007
2008 RefPtr<Label> topOfLoop = generator.newLabel();
2009 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002010 generator.emitLoopHint();
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002011 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00002012
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002013 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002014
2015 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002016 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002017 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002018
2019 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002020}
2021
2022// ------------------------------ WhileNode ------------------------------------
2023
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002024void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002025{
oliver@apple.com6a976452013-03-11 21:02:39 +00002026 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002027 RefPtr<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002028
ggaren@apple.com8e8bac42015-03-26 23:35:47 +00002029 generator.emitDebugHook(WillExecuteStatement, m_expr->firstLine(), m_expr->startOffset(), m_expr->lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002030 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002031
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002032 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002033 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002034
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002035 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002036 generator.emitNode(dst, m_statement);
2037
2038 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002039 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002040
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002041 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002042
2043 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002044
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002045 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002046}
2047
2048// ------------------------------ ForNode --------------------------------------
2049
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002050void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002051{
oliver@apple.com6a976452013-03-11 21:02:39 +00002052 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002053
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002054 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002055
2056 if (m_expr1)
2057 generator.emitNode(generator.ignoredResult(), m_expr1);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002058
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002059 RefPtr<Label> topOfLoop = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002060 if (m_expr2)
2061 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00002062
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002063 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00002064 generator.emitLoopHint();
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002065 generator.emitProfileControlFlow(m_statement->startOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002066
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002067 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002068
2069 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002070 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002071 if (m_expr3)
2072 generator.emitNode(generator.ignoredResult(), m_expr3);
2073
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00002074 if (m_expr2)
2075 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
2076 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002077 generator.emitJump(topOfLoop.get());
2078
2079 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002080 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002081}
2082
2083// ------------------------------ ForInNode ------------------------------------
2084
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002085RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002086{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002087 if (m_lexpr->isResolveNode()) {
2088 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002089 return generator.variable(ident).local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002090 }
2091
2092 if (m_lexpr->isDeconstructionNode()) {
2093 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
2094 auto binding = assignNode->bindings();
2095 if (!binding->isBindingNode())
2096 return nullptr;
2097
2098 auto simpleBinding = static_cast<BindingNode*>(binding);
2099 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002100 Variable var = generator.variable(ident);
2101 if (var.isSpecial())
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002102 return nullptr;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002103 return var.local();
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002104 }
2105
2106 return nullptr;
2107}
2108
2109void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
2110{
2111 if (m_lexpr->isResolveNode()) {
2112 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002113 Variable var = generator.variable(ident);
2114 if (RegisterID* local = var.local())
2115 generator.emitMove(local, propertyName);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002116 else {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002117 if (generator.isStrictMode())
2118 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002119 RegisterID* scope = generator.emitResolveScope(nullptr, var);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002120 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002121 generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002122 if (generator.vm()->typeProfiler())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002123 generator.emitProfileType(propertyName, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002124 }
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002125 if (generator.vm()->typeProfiler())
2126 generator.emitTypeProfilerExpressionInfo(m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002127 return;
2128 }
2129 if (m_lexpr->isDotAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002130 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2131 const Identifier& ident = assignNode->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002132 RegisterID* base = generator.emitNode(assignNode->base());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002133 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002134 generator.emitPutById(base, ident, propertyName);
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002135 if (generator.vm()->typeProfiler()) {
2136 generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
2137 generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
2138 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002139 return;
2140 }
2141 if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002142 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002143 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2144 RegisterID* subscript = generator.emitNode(assignNode->subscript());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002145 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002146 generator.emitPutByVal(base.get(), subscript, propertyName);
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002147 if (generator.vm()->typeProfiler()) {
2148 generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
2149 generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
2150 }
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002151 return;
oliver@apple.comd055db62013-10-02 19:11:04 +00002152 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002153
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002154 if (m_lexpr->isDeconstructionNode()) {
2155 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
2156 auto binding = assignNode->bindings();
2157 if (!binding->isBindingNode()) {
2158 assignNode->bindings()->bindValue(generator, propertyName);
2159 return;
2160 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002161
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002162 auto simpleBinding = static_cast<BindingNode*>(binding);
2163 const Identifier& ident = simpleBinding->boundProperty();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002164 Variable var = generator.variable(ident);
2165 if (!var.local() || var.isSpecial()) {
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002166 assignNode->bindings()->bindValue(generator, propertyName);
2167 return;
2168 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002169 generator.emitMove(var.local(), propertyName);
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002170 if (generator.vm()->typeProfiler())
saambarati1@gmail.com784581f2015-02-10 19:01:41 +00002171 generator.emitTypeProfilerExpressionInfo(simpleBinding->divotStart(), simpleBinding->divotEnd());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002172 return;
2173 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002174
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002175 RELEASE_ASSERT_NOT_REACHED();
2176}
2177
2178void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
2179{
2180 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002181 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-in statement is not a reference."));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002182 return;
2183 }
2184
2185 RefPtr<Label> end = generator.newLabel();
2186
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002187 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002188
2189 RefPtr<RegisterID> base = generator.newTemporary();
2190 RefPtr<RegisterID> length;
msaboff@apple.comb644c252015-03-24 10:05:21 +00002191 RefPtr<RegisterID> enumerator;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002192 generator.emitNode(base.get(), m_expr);
2193 RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002194 RefPtr<RegisterID> enumeratorIndex;
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002195
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002196 int profilerStartOffset = m_statement->startOffset();
2197 int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
msaboff@apple.comb644c252015-03-24 10:05:21 +00002198
2199 enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
2200
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002201 // Indexed property loop.
2202 {
2203 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2204 RefPtr<Label> loopStart = generator.newLabel();
2205 RefPtr<Label> loopEnd = generator.newLabel();
2206
msaboff@apple.comb644c252015-03-24 10:05:21 +00002207 length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002208 RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
2209 RefPtr<RegisterID> propertyName = generator.newTemporary();
2210
2211 generator.emitLabel(loopStart.get());
2212 generator.emitLoopHint();
2213
2214 RefPtr<RegisterID> result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
2215 generator.emitJumpIfFalse(result.get(), loopEnd.get());
2216 generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
2217 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2218
2219 generator.emitToIndexString(propertyName.get(), i.get());
2220 this->emitLoopHeader(generator, propertyName.get());
2221
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002222 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002223
fpizlo@apple.comcaf35052014-08-20 02:38:46 +00002224 generator.pushIndexedForInScope(local.get(), i.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002225 generator.emitNode(dst, m_statement);
2226 generator.popIndexedForInScope(local.get());
2227
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002228 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002229
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002230 generator.emitLabel(scope->continueTarget());
2231 generator.emitInc(i.get());
2232 generator.emitJump(loopStart.get());
2233
2234 generator.emitLabel(scope->breakTarget());
2235 generator.emitJump(end.get());
2236 generator.emitLabel(loopEnd.get());
2237 }
2238
2239 // Structure property loop.
2240 {
2241 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2242 RefPtr<Label> loopStart = generator.newLabel();
2243 RefPtr<Label> loopEnd = generator.newLabel();
2244
msaboff@apple.comb644c252015-03-24 10:05:21 +00002245 enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002246 RefPtr<RegisterID> propertyName = generator.newTemporary();
msaboff@apple.comb644c252015-03-24 10:05:21 +00002247 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002248
2249 generator.emitLabel(loopStart.get());
2250 generator.emitLoopHint();
2251
2252 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2253 generator.emitJumpIfTrue(result.get(), loopEnd.get());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002254 generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002255 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2256
2257 this->emitLoopHeader(generator, propertyName.get());
2258
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002259 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002260
msaboff@apple.comb644c252015-03-24 10:05:21 +00002261 generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002262 generator.emitNode(dst, m_statement);
2263 generator.popStructureForInScope(local.get());
2264
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002265 generator.emitProfileControlFlow(profilerEndOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002266
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002267 generator.emitLabel(scope->continueTarget());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002268 generator.emitInc(enumeratorIndex.get());
2269 generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002270 generator.emitJump(loopStart.get());
2271
2272 generator.emitLabel(scope->breakTarget());
2273 generator.emitJump(end.get());
2274 generator.emitLabel(loopEnd.get());
2275 }
2276
2277 // Generic property loop.
2278 {
2279 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
2280 RefPtr<Label> loopStart = generator.newLabel();
2281 RefPtr<Label> loopEnd = generator.newLabel();
2282
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002283 RefPtr<RegisterID> propertyName = generator.newTemporary();
2284
msaboff@apple.comb644c252015-03-24 10:05:21 +00002285 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002286
2287 generator.emitLabel(loopStart.get());
2288 generator.emitLoopHint();
2289
msaboff@apple.comb644c252015-03-24 10:05:21 +00002290 RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
2291 generator.emitJumpIfTrue(result.get(), loopEnd.get());
2292
2293 generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
2294 generator.emitJumpIfFalse(result.get(), scope->continueTarget());
2295
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002296 this->emitLoopHeader(generator, propertyName.get());
2297
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002298 generator.emitProfileControlFlow(profilerStartOffset);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002299
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002300 generator.emitNode(dst, m_statement);
2301
2302 generator.emitLabel(scope->continueTarget());
msaboff@apple.comb644c252015-03-24 10:05:21 +00002303 generator.emitInc(enumeratorIndex.get());
2304 generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
2305 generator.emitJump(loopStart.get());
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002306
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002307 generator.emitLabel(scope->breakTarget());
2308 generator.emitJump(end.get());
2309 generator.emitLabel(loopEnd.get());
2310 }
2311
2312 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2313 generator.emitLabel(end.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002314 generator.emitProfileControlFlow(profilerEndOffset);
fpizlo@apple.coma398a562014-08-06 21:32:55 +00002315}
2316
2317void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2318{
2319 this->emitMultiLoopBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002320}
2321
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002322// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002323void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2324{
oliver@apple.com313fcd62014-03-25 20:06:07 +00002325 if (!m_lexpr->isAssignmentLocation()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00002326 emitThrowReferenceError(generator, ASCIILiteral("Left side of for-of statement is not a reference."));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002327 return;
2328 }
utatane.tea@gmail.combc074492015-04-01 09:36:15 +00002329
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002330 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002331 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002332 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00002333 if (m_lexpr->isResolveNode()) {
2334 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002335 Variable var = generator.variable(ident);
2336 if (RegisterID* local = var.local())
2337 generator.emitMove(local, value);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002338 else {
2339 if (generator.isStrictMode())
2340 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002341 RegisterID* scope = generator.emitResolveScope(nullptr, var);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002342 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002343 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002344 if (generator.vm()->typeProfiler())
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00002345 generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
oliver@apple.com72f8a822013-10-17 01:02:34 +00002346 }
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002347 if (generator.vm()->typeProfiler())
2348 generator.emitTypeProfilerExpressionInfo(m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
oliver@apple.com72f8a822013-10-17 01:02:34 +00002349 } else if (m_lexpr->isDotAccessorNode()) {
2350 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
2351 const Identifier& ident = assignNode->identifier();
2352 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2353
2354 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2355 generator.emitPutById(base.get(), ident, value);
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002356 if (generator.vm()->typeProfiler()) {
2357 generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
2358 generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
2359 }
oliver@apple.com72f8a822013-10-17 01:02:34 +00002360 } else if (m_lexpr->isBracketAccessorNode()) {
2361 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
2362 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
2363 RegisterID* subscript = generator.emitNode(assignNode->subscript());
2364
2365 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
2366 generator.emitPutByVal(base.get(), subscript, value);
saambarati1@gmail.coma0376682015-02-10 07:40:53 +00002367 if (generator.vm()->typeProfiler()) {
2368 generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
2369 generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
2370 }
oliver@apple.com72f8a822013-10-17 01:02:34 +00002371 } else {
2372 ASSERT(m_lexpr->isDeconstructionNode());
2373 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
oliver@apple.com47784d62013-10-25 21:31:36 +00002374 assignNode->bindings()->bindValue(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002375 }
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002376 generator.emitProfileControlFlow(m_statement->startOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00002377 generator.emitNode(dst, m_statement);
2378 };
2379 generator.emitEnumeration(this, m_expr, extractor);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002380 generator.emitProfileControlFlow(m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0));
oliver@apple.com20a9bf02013-10-04 20:35:24 +00002381}
2382
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002383// ------------------------------ ContinueNode ---------------------------------
2384
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002385Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
2386{
2387 if (generator.shouldEmitDebugHooks())
2388 return 0;
2389
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002390 LabelScopePtr scope = generator.continueTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002391 ASSERT(scope);
2392
2393 if (generator.scopeDepth() != scope->scopeDepth())
2394 return 0;
2395
2396 return scope->continueTarget();
2397}
2398
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002399void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002400{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002401 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002402
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002403 LabelScopePtr scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002404 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002405
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002406 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002407 generator.emitJump(scope->continueTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002408
2409 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002410}
2411
2412// ------------------------------ BreakNode ------------------------------------
2413
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002414Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
2415{
2416 if (generator.shouldEmitDebugHooks())
2417 return 0;
2418
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002419 LabelScopePtr scope = generator.breakTarget(m_ident);
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00002420 ASSERT(scope);
2421
2422 if (generator.scopeDepth() != scope->scopeDepth())
2423 return 0;
2424
2425 return scope->breakTarget();
2426}
2427
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002428void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002429{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002430 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002431
mark.lam@apple.comee88ae02014-03-21 23:48:39 +00002432 LabelScopePtr scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002433 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002434
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002435 generator.emitPopScopes(generator.scopeRegister(), scope->scopeDepth());
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002436 generator.emitJump(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002437
2438 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002439}
2440
2441// ------------------------------ ReturnNode -----------------------------------
2442
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002443void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002444{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002445 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002446 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002447
2448 if (dst == generator.ignoredResult())
2449 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002450
2451 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002452 if (generator.vm()->typeProfiler()) {
2453 generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, nullptr);
2454 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002455 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002456 if (generator.scopeDepth()) {
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002457 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002458 generator.emitPopScopes(generator.scopeRegister(), 0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002459 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00002460
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002461 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002462 generator.emitReturn(returnRegister.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002463 generator.emitProfileControlFlow(endOffset());
2464 // Emitting an unreachable return here is needed in case this op_profile_control_flow is the
2465 // last opcode in a CodeBlock because a CodeBlock's instructions must end with a terminal opcode.
2466 if (generator.vm()->controlFlowProfiler())
2467 generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002468}
2469
2470// ------------------------------ WithNode -------------------------------------
2471
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002472void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002473{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002474 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.com170d6f22012-09-02 21:27:23 +00002475
2476 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002477 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002478 generator.emitPushWithScope(generator.scopeRegister(), scope.get());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002479 generator.emitNode(dst, m_statement);
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002480 generator.emitPopScope(generator.scopeRegister());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002481}
2482
2483// ------------------------------ CaseClauseNode --------------------------------
2484
2485inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2486{
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002487 generator.emitProfileControlFlow(m_startOffset);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002488 if (!m_statements)
2489 return;
2490 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002491}
2492
2493// ------------------------------ CaseBlockNode --------------------------------
2494
2495enum SwitchKind {
2496 SwitchUnset = 0,
2497 SwitchNumber = 1,
2498 SwitchString = 2,
2499 SwitchNeither = 3
2500};
2501
2502static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2503{
2504 for (; list; list = list->getNext()) {
2505 ExpressionNode* clauseExpression = list->getClause()->expr();
2506 literalVector.append(clauseExpression);
2507 if (clauseExpression->isNumber()) {
2508 double value = static_cast<NumberNode*>(clauseExpression)->value();
2509 int32_t intVal = static_cast<int32_t>(value);
2510 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
2511 typeForTable = SwitchNeither;
2512 break;
2513 }
2514 if (intVal < min_num)
2515 min_num = intVal;
2516 if (intVal > max_num)
2517 max_num = intVal;
2518 typeForTable = SwitchNumber;
2519 continue;
2520 }
2521 if (clauseExpression->isString()) {
2522 if (typeForTable & ~SwitchString) {
2523 typeForTable = SwitchNeither;
2524 break;
2525 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00002526 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00002527 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00002528 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002529 if (intVal < min_num)
2530 min_num = intVal;
2531 if (intVal > max_num)
2532 max_num = intVal;
2533 }
2534 typeForTable = SwitchString;
2535 continue;
2536 }
2537 typeForTable = SwitchNeither;
2538 break;
2539 }
2540}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002541
2542static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002543{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002544 size_t length = 0;
2545 for (ClauseListNode* node = list1; node; node = node->getNext())
2546 ++length;
2547 for (ClauseListNode* node = list2; node; node = node->getNext())
2548 ++length;
2549 return length;
2550}
2551
2552SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2553{
2554 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
2555 return SwitchInfo::SwitchNone;
2556
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002557 SwitchKind typeForTable = SwitchUnset;
2558 bool singleCharacterSwitch = true;
2559
2560 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2561 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2562
2563 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2564 return SwitchInfo::SwitchNone;
2565
2566 if (typeForTable == SwitchNumber) {
2567 int32_t range = max_num - min_num;
2568 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2569 return SwitchInfo::SwitchImmediate;
2570 return SwitchInfo::SwitchNone;
2571 }
2572
2573 ASSERT(typeForTable == SwitchString);
2574
2575 if (singleCharacterSwitch) {
2576 int32_t range = max_num - min_num;
2577 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2578 return SwitchInfo::SwitchCharacter;
2579 }
2580
2581 return SwitchInfo::SwitchString;
2582}
2583
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002584void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002585{
2586 RefPtr<Label> defaultLabel;
2587 Vector<RefPtr<Label>, 8> labelVector;
2588 Vector<ExpressionNode*, 8> literalVector;
2589 int32_t min_num = std::numeric_limits<int32_t>::max();
2590 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002591 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002592
2593 if (switchType != SwitchInfo::SwitchNone) {
2594 // Prepare the various labels
2595 for (uint32_t i = 0; i < literalVector.size(); i++)
2596 labelVector.append(generator.newLabel());
2597 defaultLabel = generator.newLabel();
2598 generator.beginSwitch(switchExpression, switchType);
2599 } else {
2600 // Setup jumps
2601 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2602 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2603 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2604 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2605 labelVector.append(generator.newLabel());
2606 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2607 }
2608
2609 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2610 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2611 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2612 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2613 labelVector.append(generator.newLabel());
2614 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2615 }
2616 defaultLabel = generator.newLabel();
2617 generator.emitJump(defaultLabel.get());
2618 }
2619
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002620 size_t i = 0;
2621 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2622 generator.emitLabel(labelVector[i++].get());
2623 list->getClause()->emitBytecode(generator, dst);
2624 }
2625
2626 if (m_defaultClause) {
2627 generator.emitLabel(defaultLabel.get());
2628 m_defaultClause->emitBytecode(generator, dst);
2629 }
2630
2631 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2632 generator.emitLabel(labelVector[i++].get());
2633 list->getClause()->emitBytecode(generator, dst);
2634 }
2635 if (!m_defaultClause)
2636 generator.emitLabel(defaultLabel.get());
2637
2638 ASSERT(i == labelVector.size());
2639 if (switchType != SwitchInfo::SwitchNone) {
2640 ASSERT(labelVector.size() == literalVector.size());
2641 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2642 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002643}
2644
2645// ------------------------------ SwitchNode -----------------------------------
2646
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002647void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002648{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002649 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002650
oliver@apple.com6a976452013-03-11 21:02:39 +00002651 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002652
2653 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002654 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002655
2656 generator.emitLabel(scope->breakTarget());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002657 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002658}
2659
2660// ------------------------------ LabelNode ------------------------------------
2661
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002662void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002663{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002664 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002665
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002666 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002667
oliver@apple.com6a976452013-03-11 21:02:39 +00002668 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002669 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002670
2671 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002672}
2673
2674// ------------------------------ ThrowNode ------------------------------------
2675
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002676void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002677{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002678 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002679
2680 if (dst == generator.ignoredResult())
2681 dst = 0;
2682 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002683 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002684 generator.emitThrow(expr.get());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002685
2686 generator.emitProfileControlFlow(endOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002687}
2688
2689// ------------------------------ TryNode --------------------------------------
2690
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002691void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002692{
2693 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2694 // optimizer knows they may be jumped to from anywhere.
2695
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002696 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002697
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002698 ASSERT(m_catchBlock || m_finallyBlock);
2699
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002700 RefPtr<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002701 generator.emitLabel(tryStartLabel.get());
2702
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002703 if (m_finallyBlock)
2704 generator.pushFinallyContext(m_finallyBlock);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002705 TryData* tryData = generator.pushTry(tryStartLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002706
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002707 generator.emitNode(dst, m_tryBlock);
2708
2709 if (m_catchBlock) {
2710 RefPtr<Label> catchEndLabel = generator.newLabel();
2711
2712 // Normal path: jump over the catch block.
2713 generator.emitJump(catchEndLabel.get());
2714
2715 // Uncaught exception path: the catch block.
2716 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002717 RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
2718
2719 if (m_finallyBlock) {
2720 // If the catch block throws an exception and we have a finally block, then the finally
2721 // block should "catch" that exception.
2722 tryData = generator.pushTry(here.get());
2723 }
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002724
2725 generator.emitPushCatchScope(generator.scopeRegister(), m_exceptionIdent, exceptionRegister.get(), DontDelete);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002726 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002727 generator.emitNode(dst, m_catchBlock);
msaboff@apple.comc5b95392014-10-31 21:27:10 +00002728 generator.emitPopScope(generator.scopeRegister());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002729 generator.emitLabel(catchEndLabel.get());
2730 }
2731
2732 if (m_finallyBlock) {
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002733 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2734
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002735 generator.popFinallyContext();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002736
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002737 RefPtr<Label> finallyEndLabel = generator.newLabel();
2738
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002739 int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() + 1 : m_tryBlock->endOffset() + 1;
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002740
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002741 // Normal path: run the finally code, and jump to the end.
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002742 generator.emitProfileControlFlow(finallyStartOffset);
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002743 generator.emitNode(dst, m_finallyBlock);
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002744 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002745 generator.emitJump(finallyEndLabel.get());
2746
2747 // Uncaught exception path: invoke the finally block, then re-throw the exception.
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002748 RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002749 generator.emitProfileControlFlow(finallyStartOffset);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002750 generator.emitNode(dst, m_finallyBlock);
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002751 generator.emitThrow(tempExceptionRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002752
2753 generator.emitLabel(finallyEndLabel.get());
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002754 generator.emitProfileControlFlow(m_finallyBlock->endOffset() + 1);
saambarati1@gmail.comd60d9412015-01-20 04:47:55 +00002755 } else
saambarati1@gmail.com15952502015-02-23 22:10:51 +00002756 generator.emitProfileControlFlow(m_catchBlock->endOffset() + 1);
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002757
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002758}
2759
2760// ------------------------------ ScopeNode -----------------------------
2761
2762inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2763{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002764 if (!m_statements)
2765 return;
2766 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002767}
2768
2769// ------------------------------ ProgramNode -----------------------------
2770
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002771void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002772{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002773 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002774
2775 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2776 generator.emitLoad(dstRegister.get(), jsUndefined());
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002777 generator.emitProfileControlFlow(startStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002778 emitStatementsBytecode(generator, dstRegister.get());
2779
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002780 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002781 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002782}
2783
2784// ------------------------------ EvalNode -----------------------------
2785
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002786void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002787{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002788 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002789
2790 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2791 generator.emitLoad(dstRegister.get(), jsUndefined());
2792 emitStatementsBytecode(generator, dstRegister.get());
2793
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002794 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002795 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002796}
2797
2798// ------------------------------ FunctionBodyNode -----------------------------
2799
ggaren@apple.com6f851d72014-12-04 23:47:49 +00002800void FunctionBodyNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2801{
2802}
2803
2804void FunctionNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002805{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002806 if (generator.vm()->typeProfiler()) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002807 for (size_t i = 0; i < m_parameters->size(); i++) {
2808 // FIXME: Handle Destructuring assignments into arguments.
2809 if (!m_parameters->at(i)->isBindingNode())
2810 continue;
2811 BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i));
2812 RegisterID reg(CallFrame::argumentOffset(i));
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002813 generator.emitProfileType(&reg, ProfileTypeBytecodeFunctionArgument, nullptr);
2814 generator.emitTypeProfilerExpressionInfo(parameter->divotStart(), parameter->divotEnd());
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00002815 }
2816 }
2817
saambarati1@gmail.comb4f28a52014-12-05 05:58:07 +00002818 generator.emitProfileControlFlow(startStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002819 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002820 emitStatementsBytecode(generator, generator.ignoredResult());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002821
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002822 StatementNode* singleStatement = this->singleStatement();
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002823 ReturnNode* returnNode = 0;
2824
2825 // Check for a return statement at the end of a function composed of a single block.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002826 if (singleStatement && singleStatement->isBlock()) {
2827 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2828 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002829 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002830 }
2831
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002832 // If there is no return we must automatically insert one.
2833 if (!returnNode) {
2834 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00002835 if (generator.vm()->typeProfiler())
2836 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 +00002837 ASSERT(startOffset() >= lineStartOffset());
2838 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002839 generator.emitReturn(r0);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002840 return;
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002841 }
commit-queue@webkit.org50b07122015-04-25 06:57:12 +00002842
2843 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
2844 if (static_cast<BlockNode*>(singleStatement)->singleStatement()) {
2845 ExpressionNode* returnValueExpression = returnNode->value();
2846 if (returnValueExpression && returnValueExpression->isSubtract()) {
2847 ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
2848 ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
2849 if (lhsExpression->isResolveNode()
2850 && rhsExpression->isResolveNode()
2851 && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
2852 && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
2853
2854 generator.setIsNumericCompareFunction(true);
2855 }
2856 }
2857 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002858}
2859
2860// ------------------------------ FuncDeclNode ---------------------------------
2861
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002862void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002863{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002864}
2865
2866// ------------------------------ FuncExprNode ---------------------------------
2867
2868RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2869{
2870 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2871}
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00002872
2873#if ENABLE(ES6_CLASS_SYNTAX)
2874// ------------------------------ ClassDeclNode ---------------------------------
2875
2876void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2877{
2878 generator.emitNode(dst, m_classDeclaration);
2879}
2880
2881// ------------------------------ ClassExprNode ---------------------------------
2882
2883RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2884{
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002885 RefPtr<RegisterID> superclass;
2886 if (m_classHeritage) {
2887 superclass = generator.newTemporary();
2888 generator.emitNode(superclass.get(), m_classHeritage);
2889 }
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00002890
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00002891 RefPtr<RegisterID> constructor;
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00002892
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002893 // FIXME: Make the prototype non-configurable & non-writable.
rniwa@webkit.orgd81805e2015-03-17 04:02:52 +00002894 if (m_constructorExpression)
2895 constructor = generator.emitNode(dst, m_constructorExpression);
2896 else {
2897 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
2898 m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base, m_name);
2899 }
2900
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00002901 const auto& propertyNames = generator.propertyNames();
2902 RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary());
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00002903
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002904 if (superclass) {
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00002905 RefPtr<RegisterID> protoParent = generator.newTemporary();
2906 generator.emitLoad(protoParent.get(), jsNull());
2907
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002908 RefPtr<RegisterID> tempRegister = generator.newTemporary();
2909 RefPtr<Label> superclassIsNullLabel = generator.newLabel();
2910 generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
2911
2912 // FIXME: Throw TypeError if it's a generator function.
2913 RefPtr<Label> superclassIsObjectLabel = generator.newLabel();
2914 generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
2915 generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
2916 generator.emitLabel(superclassIsObjectLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002917 generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
2918
2919 RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
2920 generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
2921 generator.emitThrowTypeError(ASCIILiteral("The superclass's prototype is not an object."));
2922 generator.emitLabel(protoParentIsObjectOrNullLabel.get());
2923
2924 generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
rniwa@webkit.org33c69e42015-03-31 01:59:31 +00002925 generator.emitLabel(superclassIsNullLabel.get());
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002926 generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
2927
rniwa@webkit.org059ef9b2015-03-09 23:47:06 +00002928 emitPutHomeObject(generator, constructor.get(), prototype.get());
2929 }
2930
rniwa@webkit.org49d0cc12015-04-25 22:03:30 +00002931 RefPtr<RegisterID> constructorNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.constructor);
2932 generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
2933 BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
2934
2935 RefPtr<RegisterID> prototypeNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.prototype);
2936 generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
2937
rniwa@webkit.org65c9b0d2015-01-29 22:59:19 +00002938 if (m_staticMethods)
2939 generator.emitNode(constructor.get(), m_staticMethods);
2940
2941 if (m_instanceMethods)
2942 generator.emitNode(prototype.get(), m_instanceMethods);
2943
2944 return generator.moveToDestinationIfNeeded(dst, constructor.get());
2945}
2946#endif
oliver@apple.comd055db62013-10-02 19:11:04 +00002947
2948// ------------------------------ DeconstructingAssignmentNode -----------------
2949RegisterID* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2950{
2951 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
2952 return result;
2953 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
2954 generator.emitNode(initializer.get(), m_initializer);
oliver@apple.com47784d62013-10-25 21:31:36 +00002955 m_bindings->bindValue(generator, initializer.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002956 return generator.moveToDestinationIfNeeded(dst, initializer.get());
2957}
2958
2959DeconstructionPatternNode::~DeconstructionPatternNode()
2960{
2961}
2962
oliver@apple.com47784d62013-10-25 21:31:36 +00002963void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00002964{
2965 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2966 auto target = m_targetPatterns[i];
2967 if (!target)
2968 continue;
2969 RefPtr<RegisterID> temp = generator.newTemporary();
2970 generator.emitLoad(temp.get(), jsNumber(i));
2971 generator.emitGetByVal(temp.get(), rhs, temp.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00002972 target->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002973 }
2974}
2975
2976RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
2977{
oliver@apple.comd055db62013-10-02 19:11:04 +00002978 if (!rhs->isSimpleArray())
2979 return 0;
oliver@apple.com47784d62013-10-25 21:31:36 +00002980
oliver@apple.com2bae57a2013-11-12 20:55:29 +00002981 RefPtr<RegisterID> resultRegister;
2982 if (dst && dst != generator.ignoredResult())
2983 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
oliver@apple.comd055db62013-10-02 19:11:04 +00002984 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
2985 Vector<ExpressionNode*> elements;
2986 for (; elementNodes; elementNodes = elementNodes->next())
2987 elements.append(elementNodes->value());
2988 if (m_targetPatterns.size() != elements.size())
2989 return 0;
2990 Vector<RefPtr<RegisterID>> registers;
2991 registers.reserveCapacity(m_targetPatterns.size());
2992 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2993 registers.uncheckedAppend(generator.newTemporary());
2994 generator.emitNode(registers.last().get(), elements[i]);
oliver@apple.com2bae57a2013-11-12 20:55:29 +00002995 if (resultRegister)
2996 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
oliver@apple.comd055db62013-10-02 19:11:04 +00002997 }
2998
2999 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3000 if (m_targetPatterns[i])
oliver@apple.com47784d62013-10-25 21:31:36 +00003001 m_targetPatterns[i]->bindValue(generator, registers[i].get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003002 }
oliver@apple.com2bae57a2013-11-12 20:55:29 +00003003 if (resultRegister)
3004 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
oliver@apple.com47784d62013-10-25 21:31:36 +00003005 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
oliver@apple.comd055db62013-10-02 19:11:04 +00003006}
3007
3008void ArrayPatternNode::toString(StringBuilder& builder) const
3009{
3010 builder.append('[');
3011 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3012 if (!m_targetPatterns[i]) {
3013 builder.append(',');
3014 continue;
3015 }
3016 m_targetPatterns[i]->toString(builder);
3017 if (i < m_targetPatterns.size() - 1)
3018 builder.append(',');
3019 }
3020 builder.append(']');
3021}
3022
3023void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3024{
3025 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3026 if (DeconstructionPatternNode* node = m_targetPatterns[i].get())
3027 node->collectBoundIdentifiers(identifiers);
3028 }
3029}
3030
3031void ObjectPatternNode::toString(StringBuilder& builder) const
3032{
3033 builder.append('{');
3034 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
antti@apple.comf3e3f5e2015-03-02 21:51:13 +00003035 if (m_targetPatterns[i].wasString)
3036 appendQuotedJSONStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
3037 else
oliver@apple.comd055db62013-10-02 19:11:04 +00003038 builder.append(m_targetPatterns[i].propertyName.string());
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00003039 builder.append(':');
oliver@apple.comd055db62013-10-02 19:11:04 +00003040 m_targetPatterns[i].pattern->toString(builder);
3041 if (i < m_targetPatterns.size() - 1)
3042 builder.append(',');
3043 }
3044 builder.append('}');
3045}
3046
oliver@apple.com47784d62013-10-25 21:31:36 +00003047void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003048{
3049 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
3050 auto& target = m_targetPatterns[i];
3051 RefPtr<RegisterID> temp = generator.newTemporary();
3052 generator.emitGetById(temp.get(), rhs, target.propertyName);
oliver@apple.com47784d62013-10-25 21:31:36 +00003053 target.pattern->bindValue(generator, temp.get());
oliver@apple.comd055db62013-10-02 19:11:04 +00003054 }
3055}
3056
3057void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3058{
3059 for (size_t i = 0; i < m_targetPatterns.size(); i++)
3060 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
3061}
3062
oliver@apple.com47784d62013-10-25 21:31:36 +00003063void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
oliver@apple.comd055db62013-10-02 19:11:04 +00003064{
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003065 Variable var = generator.variable(m_boundProperty);
3066 if (RegisterID* local = var.local()) {
3067 if (var.isReadOnly()) {
oliver@apple.comd055db62013-10-02 19:11:04 +00003068 generator.emitReadOnlyExceptionIfNeeded();
3069 return;
3070 }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003071 generator.emitMove(local, value);
saambarati1@gmail.comaf59ca42014-08-29 22:52:51 +00003072 if (generator.vm()->typeProfiler())
3073 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
oliver@apple.comd055db62013-10-02 19:11:04 +00003074 return;
3075 }
3076 if (generator.isStrictMode())
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003077 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003078 RegisterID* scope = generator.emitResolveScope(nullptr, var);
akling@apple.combdf5d1d2014-01-21 01:10:29 +00003079 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003080 generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
saambarati1@gmail.comaf59ca42014-08-29 22:52:51 +00003081 if (generator.vm()->typeProfiler()) {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003082 generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty);
saambarati1@gmail.comaf59ca42014-08-29 22:52:51 +00003083 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
3084 }
oliver@apple.comd055db62013-10-02 19:11:04 +00003085 return;
3086}
3087
3088void BindingNode::toString(StringBuilder& builder) const
3089{
3090 builder.append(m_boundProperty.string());
3091}
3092
3093void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
3094{
3095 identifiers.append(m_boundProperty);
3096}
oliver@apple.com72f8a822013-10-17 01:02:34 +00003097
3098RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
3099{
3100 RELEASE_ASSERT_NOT_REACHED();
3101 return 0;
3102}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00003103
3104} // namespace JSC