blob: dd37178106b0e9cebf10ed68399d64db5094653b [file] [log] [blame]
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
mark.lam@apple.comfaa53932013-03-20 09:09:38 +00004* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00005* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +00008 * Copyright (C) 2012 Igalia, S.L.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00009*
10* This library is free software; you can redistribute it and/or
11* modify it under the terms of the GNU Library General Public
12* License as published by the Free Software Foundation; either
13* version 2 of the License, or (at your option) any later version.
14*
15* This library is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18* Library General Public License for more details.
19*
20* You should have received a copy of the GNU Library General Public License
21* along with this library; see the file COPYING.LIB. If not, write to
22* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23* Boston, MA 02110-1301, USA.
24*
25*/
26
27#include "config.h"
28#include "Nodes.h"
29#include "NodeConstructors.h"
30
31#include "BytecodeGenerator.h"
32#include "CallFrame.h"
33#include "Debugger.h"
34#include "JIT.h"
35#include "JSFunction.h"
36#include "JSGlobalObject.h"
ggaren@apple.comce2b6672012-08-28 17:52:18 +000037#include "JSNameScope.h"
oliver@apple.comd055db62013-10-02 19:11:04 +000038#include "JSONObject.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000039#include "LabelScope.h"
40#include "Lexer.h"
41#include "Operations.h"
42#include "Parser.h"
43#include "PropertyNameArray.h"
zherczeg@webkit.org17dc93a2010-06-22 19:16:57 +000044#include "RegExpCache.h"
mjs@apple.comaed3cef2009-12-09 01:29:52 +000045#include "RegExpObject.h"
46#include "SamplingTool.h"
47#include <wtf/Assertions.h>
48#include <wtf/RefCountedLeakCounter.h>
49#include <wtf/Threading.h>
50
51using namespace WTF;
52
53namespace JSC {
54
55/*
56 Details of the emitBytecode function.
57
58 Return value: The register holding the production's value.
59 dst: An optional parameter specifying the most efficient destination at
60 which to store the production's value. The callee must honor dst.
61
62 The dst argument provides for a crude form of copy propagation. For example,
63
64 x = 1
65
66 becomes
67
68 load r[x], 1
69
70 instead of
71
72 load r0, 1
73 mov r[x], r0
74
75 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
76*/
77
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +000078void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
79{
80 RegisterID* result = generator.emitNode(this);
81 if (fallThroughMode == FallThroughMeansTrue)
82 generator.emitJumpIfFalse(result, falseTarget);
83 else
84 generator.emitJumpIfTrue(result, trueTarget);
85}
86
mjs@apple.comaed3cef2009-12-09 01:29:52 +000087// ------------------------------ ThrowableExpressionData --------------------------------
88
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000089RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000090{
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +000091 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com4920ae92010-11-12 03:06:07 +000092 generator.emitThrowReferenceError(message);
93 return generator.newTemporary();
mjs@apple.comaed3cef2009-12-09 01:29:52 +000094}
95
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000096// ------------------------------ ConstantNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +000097
ggaren@apple.com81c68cc2013-04-27 06:43:33 +000098void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +000099{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000100 TriState value = jsValue(generator).pureToBoolean();
101 if (value == MixedTriState)
102 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
103 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
104 generator.emitJump(trueTarget);
105 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
106 generator.emitJump(falseTarget);
107
108 // All other cases are unconditional fall-throughs, like "if (true)".
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000109}
110
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000111RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000112{
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000113 if (dst == generator.ignoredResult())
114 return 0;
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000115 return generator.emitLoad(dst, jsValue(generator));
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000116}
117
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000118JSValue StringNode::jsValue(BytecodeGenerator& generator) const
fpizlo@apple.com335ba392013-04-26 00:40:27 +0000119{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +0000120 return generator.addStringConstant(m_value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000121}
122
123// ------------------------------ RegExpNode -----------------------------------
124
125RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
126{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000127 if (dst == generator.ignoredResult())
128 return 0;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000129 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 +0000130}
131
132// ------------------------------ ThisNode -------------------------------------
133
134RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
135{
136 if (dst == generator.ignoredResult())
137 return 0;
138 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
139}
140
141// ------------------------------ ResolveNode ----------------------------------
142
143bool ResolveNode::isPure(BytecodeGenerator& generator) const
144{
oliver@apple.com58c86752013-07-25 04:02:40 +0000145 return generator.local(m_ident).get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000146}
147
148RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
149{
oliver@apple.com58c86752013-07-25 04:02:40 +0000150 if (Local local = generator.local(m_ident)) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000151 if (dst == generator.ignoredResult())
152 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +0000153 return generator.moveToDestinationIfNeeded(dst, local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000154 }
155
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000156 JSTextPosition divot = m_start + m_ident.length();
157 generator.emitExpressionInfo(divot, m_start, divot);
oliver@apple.com58c86752013-07-25 04:02:40 +0000158 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
159 return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000160}
161
162// ------------------------------ ArrayNode ------------------------------------
163
164RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
165{
166 // FIXME: Should we put all of this code into emitNewArray?
167
168 unsigned length = 0;
169 ElementNode* firstPutElement;
170 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
oliver@apple.com72f8a822013-10-17 01:02:34 +0000171 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000172 break;
173 ++length;
174 }
175
176 if (!firstPutElement && !m_elision)
oliver@apple.coma991d692011-06-14 23:39:25 +0000177 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000178
oliver@apple.coma991d692011-06-14 23:39:25 +0000179 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
oliver@apple.com72f8a822013-10-17 01:02:34 +0000180 ElementNode* n = firstPutElement;
181 for (; n; n = n->next()) {
182 if (n->value()->isSpreadExpression())
183 goto handleSpread;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000184 RegisterID* value = generator.emitNode(n->value());
185 length += n->elision();
186 generator.emitPutByIndex(array.get(), length++, value);
187 }
188
189 if (m_elision) {
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000190 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000191 generator.emitPutById(array.get(), generator.propertyNames().length, value);
192 }
193
194 return generator.moveToDestinationIfNeeded(dst, array.get());
oliver@apple.com72f8a822013-10-17 01:02:34 +0000195
196handleSpread:
197 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
198 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
199 {
200 generator.emitPutByVal(array.get(), index.get(), value);
201 generator.emitInc(index.get());
202 };
203 for (; n; n = n->next()) {
204 if (n->elision())
205 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
206 if (n->value()->isSpreadExpression()) {
207 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
208 generator.emitEnumeration(spread, spread->expression(), spreader);
209 } else {
210 generator.emitPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
211 generator.emitInc(index.get());
212 }
213 }
214
215 if (m_elision) {
216 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
217 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
218 }
219 return generator.moveToDestinationIfNeeded(dst, array.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000220}
221
222bool ArrayNode::isSimpleArray() const
223{
224 if (m_elision || m_optional)
225 return false;
226 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
227 if (ptr->elision())
228 return false;
229 }
230 return true;
231}
232
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000233ArgumentListNode* ArrayNode::toArgumentList(VM* vm, int lineNumber, int startPosition) const
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000234{
235 ASSERT(!m_elision && !m_optional);
236 ElementNode* ptr = m_element;
237 if (!ptr)
238 return 0;
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000239 JSTokenLocation location;
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +0000240 location.line = lineNumber;
mark.lam@apple.com5b45f902013-07-09 16:15:12 +0000241 location.startOffset = startPosition;
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000242 ArgumentListNode* head = new (vm) ArgumentListNode(location, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000243 ArgumentListNode* tail = head;
244 ptr = ptr->next();
245 for (; ptr; ptr = ptr->next()) {
246 ASSERT(!ptr->elision());
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +0000247 tail = new (vm) ArgumentListNode(location, tail, ptr->value());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000248 }
249 return head;
250}
251
252// ------------------------------ ObjectLiteralNode ----------------------------
253
254RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
255{
256 if (!m_list) {
257 if (dst == generator.ignoredResult())
258 return 0;
259 return generator.emitNewObject(generator.finalDestination(dst));
260 }
261 return generator.emitNode(dst, m_list);
262}
263
264// ------------------------------ PropertyListNode -----------------------------
265
266RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
267{
268 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
269
270 generator.emitNewObject(newObj.get());
271
barraclough@apple.com09a55682012-01-30 18:28:39 +0000272 // Fast case: this loop just handles regular value properties.
273 PropertyListNode* p = this;
274 for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next)
275 generator.emitDirectPutById(newObj.get(), p->m_node->name(), generator.emitNode(p->m_node->m_assign));
276
277 // Were there any get/set properties?
278 if (p) {
279 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
280 typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
281 GetterSetterMap map;
282
283 // Build a map, pairing get/set values together.
284 for (PropertyListNode* q = p; q; q = q->m_next) {
285 PropertyNode* node = q->m_node;
286 if (node->m_type == PropertyNode::Constant)
287 continue;
288
paroga@webkit.orgf990c252012-02-20 23:37:01 +0000289 GetterSetterPair pair(node, static_cast<PropertyNode*>(0));
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +0000290 GetterSetterMap::AddResult result = map.add(node->name().impl(), pair);
291 if (!result.isNewEntry)
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000292 result.iterator->value.second = node;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000293 }
294
295 // Iterate over the remaining properties in the list.
296 for (; p; p = p->m_next) {
297 PropertyNode* node = p->m_node;
298 RegisterID* value = generator.emitNode(node->m_assign);
299
300 // Handle regular values.
301 if (node->m_type == PropertyNode::Constant) {
302 generator.emitDirectPutById(newObj.get(), node->name(), value);
303 continue;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000304 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000305
306 // This is a get/set property, find its entry in the map.
307 ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
308 GetterSetterMap::iterator it = map.find(node->name().impl());
309 ASSERT(it != map.end());
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000310 GetterSetterPair& pair = it->value;
barraclough@apple.com09a55682012-01-30 18:28:39 +0000311
312 // Was this already generated as a part of its partner?
313 if (pair.second == node)
314 continue;
315
316 // Generate the paired node now.
317 RefPtr<RegisterID> getterReg;
318 RefPtr<RegisterID> setterReg;
319
320 if (node->m_type == PropertyNode::Getter) {
321 getterReg = value;
322 if (pair.second) {
323 ASSERT(pair.second->m_type == PropertyNode::Setter);
324 setterReg = generator.emitNode(pair.second->m_assign);
325 } else {
326 setterReg = generator.newTemporary();
327 generator.emitLoad(setterReg.get(), jsUndefined());
328 }
329 } else {
330 ASSERT(node->m_type == PropertyNode::Setter);
331 setterReg = value;
332 if (pair.second) {
333 ASSERT(pair.second->m_type == PropertyNode::Getter);
334 getterReg = generator.emitNode(pair.second->m_assign);
335 } else {
336 getterReg = generator.newTemporary();
337 generator.emitLoad(getterReg.get(), jsUndefined());
338 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000339 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000340
341 generator.emitPutGetterSetter(newObj.get(), node->name(), getterReg.get(), setterReg.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000342 }
343 }
barraclough@apple.com09a55682012-01-30 18:28:39 +0000344
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000345 return generator.moveToDestinationIfNeeded(dst, newObj.get());
346}
347
348// ------------------------------ BracketAccessorNode --------------------------------
349
350RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
351{
ggaren@apple.com13e02b92012-09-20 19:51:58 +0000352 if (m_base->isResolveNode()
353 && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())
354 && !generator.symbolTable().slowArguments()) {
oliver@apple.com74e00b02010-09-25 21:42:00 +0000355 RegisterID* property = generator.emitNode(m_subscript);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000356 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com74e00b02010-09-25 21:42:00 +0000357 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
358 }
359
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000360 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
361 RegisterID* property = generator.emitNode(m_subscript);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000362 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000363 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
364}
365
366// ------------------------------ DotAccessorNode --------------------------------
367
368RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
369{
oliver@apple.com74e00b02010-09-25 21:42:00 +0000370 if (m_ident == generator.propertyNames().length) {
371 if (!m_base->isResolveNode())
372 goto nonArgumentsPath;
373 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
374 if (!generator.willResolveToArguments(resolveNode->identifier()))
375 goto nonArgumentsPath;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000376 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com74e00b02010-09-25 21:42:00 +0000377 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
378 }
379
380nonArgumentsPath:
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000381 RegisterID* base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000382 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000383 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
384}
385
386// ------------------------------ ArgumentListNode -----------------------------
387
388RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
389{
390 ASSERT(m_expr);
391 return generator.emitNode(dst, m_expr);
392}
393
394// ------------------------------ NewExprNode ----------------------------------
395
396RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
397{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000398 ExpectedFunction expectedFunction;
399 if (m_expr->isResolveNode())
400 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
401 else
402 expectedFunction = NoExpectedFunction;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000403 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000404 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000405 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000406 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000407}
408
oliver@apple.com72f8a822013-10-17 01:02:34 +0000409CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000410 : m_argumentsNode(argumentsNode)
411{
commit-queue@webkit.org90ba1872010-11-17 08:05:39 +0000412 if (generator.shouldEmitProfileHooks())
413 m_profileHookRegister = generator.newTemporary();
ggaren@apple.com50c5ac22011-11-14 23:16:27 +0000414
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000415 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
ggaren@apple.com0af14682011-12-12 00:35:51 +0000416 if (argumentsNode) {
417 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
418 ++argumentCountIncludingThis;
419 }
420
421 m_argv.grow(argumentCountIncludingThis);
422 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
423 m_argv[i] = generator.newTemporary();
msaboff@apple.comb70e41b2013-09-13 18:03:55 +0000424 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 +0000425 }
ggaren@apple.com50c5ac22011-11-14 23:16:27 +0000426}
427
428inline void CallArguments::newArgument(BytecodeGenerator& generator)
429{
430 RefPtr<RegisterID> tmp = generator.newTemporary();
431 ASSERT(m_argv.isEmpty() || tmp->index() == m_argv.last()->index() + 1); // Calling convention assumes that all arguments are contiguous.
432 m_argv.append(tmp.release());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000433}
434
435// ------------------------------ EvalFunctionCallNode ----------------------------------
436
437RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
438{
oliver@apple.com58c86752013-07-25 04:02:40 +0000439 if (Local local = generator.local(generator.propertyNames().eval)) {
440 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
441 CallArguments callArguments(generator, m_args);
442 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000443 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000444 }
445
446 RefPtr<RegisterID> func = generator.newTemporary();
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000447 CallArguments callArguments(generator, m_args);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000448 JSTextPosition newDivot = divotStart() + 4;
449 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
oliver@apple.com58c86752013-07-25 04:02:40 +0000450 generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval);
451 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000452 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000453}
454
455// ------------------------------ FunctionCallValueNode ----------------------------------
456
457RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
458{
459 RefPtr<RegisterID> func = generator.emitNode(m_expr);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000460 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000461 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000462 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000463 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000464}
465
466// ------------------------------ FunctionCallResolveNode ----------------------------------
467
468RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
469{
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000470 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000471
oliver@apple.com58c86752013-07-25 04:02:40 +0000472 if (Local local = generator.local(m_ident)) {
473 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000474 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000475 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000476 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
fpizlo@apple.com4500e352012-10-17 21:39:11 +0000477 // This passes NoExpectedFunction because we expect that if the function is in a
478 // local variable, then it's not one of our built-in constructors.
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000479 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000480 }
481
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000482 RefPtr<RegisterID> func = generator.newTemporary();
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000483 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000484 CallArguments callArguments(generator, m_args);
commit-queue@webkit.org2fea7402012-02-01 19:37:00 +0000485
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000486 JSTextPosition newDivot = divotStart() + m_ident.length();
487 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
oliver@apple.com58c86752013-07-25 04:02:40 +0000488 generator.emitResolveScope(callArguments.thisRegister(), m_ident);
489 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000490 return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000491}
492
493// ------------------------------ FunctionCallBracketNode ----------------------------------
494
495RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
496{
497 RefPtr<RegisterID> base = generator.emitNode(m_base);
498 RegisterID* property = generator.emitNode(m_subscript);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000499 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000500 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000501 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000502 CallArguments callArguments(generator, m_args);
503 generator.emitMove(callArguments.thisRegister(), base.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000504 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000505}
506
507// ------------------------------ FunctionCallDotNode ----------------------------------
508
509RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
510{
511 RefPtr<RegisterID> function = generator.tempDestination(dst);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000512 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000513 CallArguments callArguments(generator, m_args);
514 generator.emitNode(callArguments.thisRegister(), m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000515 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000516 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000517 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000518}
519
520RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
521{
522 RefPtr<Label> realCall = generator.newLabel();
523 RefPtr<Label> end = generator.newLabel();
524 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000525 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000526 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000527 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000528 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
529 {
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000530 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000531 ArgumentListNode* oldList = m_args->m_listNode;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000532 m_args->m_listNode = m_args->m_listNode->m_next;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000533
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000534 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
535 CallArguments callArguments(generator, m_args);
536 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000537 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000538 generator.emitJump(end.get());
539
540 m_args->m_listNode = oldList;
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000541 } else {
542 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
543 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000544 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000545 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000546 generator.emitJump(end.get());
547 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000548 }
549 generator.emitLabel(realCall.get());
550 {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000551 CallArguments callArguments(generator, m_args);
552 generator.emitMove(callArguments.thisRegister(), base.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000553 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000554 }
555 generator.emitLabel(end.get());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000556 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000557}
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000558
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000559static bool areTrivialApplyArguments(ArgumentsNode* args)
560{
561 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
562 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
563}
564
565RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
566{
567 // A few simple cases can be trivially handled as ordinary function calls.
568 // function.apply(), function.apply(arg) -> identical to function.call
569 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
570 bool mayBeCall = areTrivialApplyArguments(m_args);
571
572 RefPtr<Label> realCall = generator.newLabel();
573 RefPtr<Label> end = generator.newLabel();
574 RefPtr<RegisterID> base = generator.emitNode(m_base);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000575 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000576 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000577 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000578 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
579 {
580 if (mayBeCall) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000581 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000582 ArgumentListNode* oldList = m_args->m_listNode;
583 if (m_args->m_listNode->m_next) {
584 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
585 ASSERT(!m_args->m_listNode->m_next->m_next);
mark.lam@apple.com0d5fdb92013-07-24 00:41:46 +0000586 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.vm(), 0, 0);
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000587 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
588 CallArguments callArguments(generator, m_args);
589 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000590 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000591 } else {
592 m_args->m_listNode = m_args->m_listNode->m_next;
593 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
594 CallArguments callArguments(generator, m_args);
595 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000596 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000597 }
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000598 m_args->m_listNode = oldList;
599 } else {
600 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
601 CallArguments callArguments(generator, m_args);
oliver@apple.com64126552010-10-18 18:32:39 +0000602 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000603 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000604 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000605 } else {
606 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
fpizlo@apple.com5da687a2011-11-21 04:35:38 +0000607 RefPtr<RegisterID> profileHookRegister;
608 if (generator.shouldEmitProfileHooks())
609 profileHookRegister = generator.newTemporary();
ggaren@apple.combcf06d32012-01-12 00:14:42 +0000610 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000611 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
612 RefPtr<RegisterID> argsRegister;
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000613 ArgumentListNode* args = m_args->m_listNode->m_next;
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000614 if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()))
615 argsRegister = generator.uncheckedRegisterForArguments();
616 else
617 argsRegister = generator.emitNode(args->m_expr);
618
619 // Function.prototype.apply ignores extra arguments, but we still
620 // need to evaluate them for side effects.
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000621 while ((args = args->m_next))
622 generator.emitNode(args->m_expr);
623
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000624 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000625 }
626 generator.emitJump(end.get());
627 }
628 generator.emitLabel(realCall.get());
629 {
barraclough@apple.com9835d1d2010-06-01 23:13:23 +0000630 CallArguments callArguments(generator, m_args);
631 generator.emitMove(callArguments.thisRegister(), base.get());
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000632 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000633 }
634 generator.emitLabel(end.get());
oliver@apple.comcf0e6c42013-07-25 04:01:45 +0000635 return returnValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000636}
637
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000638// ------------------------------ PostfixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000639
ggaren@apple.comf3036112013-04-27 23:14:04 +0000640static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000641{
ggaren@apple.comf3036112013-04-27 23:14:04 +0000642 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000643}
644
645static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
646{
ggaren@apple.comf3036112013-04-27 23:14:04 +0000647 if (dst == srcDst)
648 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
649 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
650 emitIncOrDec(generator, srcDst, oper);
651 return generator.moveToDestinationIfNeeded(dst, tmp.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000652}
653
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000654RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000655{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000656 if (dst == generator.ignoredResult())
657 return PrefixNode::emitResolve(generator, dst);
658
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000659 ASSERT(m_expr->isResolveNode());
660 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
661 const Identifier& ident = resolve->identifier();
662
oliver@apple.com58c86752013-07-25 04:02:40 +0000663 if (Local local = generator.local(ident)) {
664 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +0000665 generator.emitReadOnlyExceptionIfNeeded();
oliver@apple.com58c86752013-07-25 04:02:40 +0000666 local = Local(generator.emitMove(generator.tempDestination(dst), local.get()), 0);
ggaren@apple.com6e309822012-09-05 21:44:43 +0000667 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000668 return emitPostIncOrDec(generator, generator.finalDestination(dst), local.get(), m_operator);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000669 }
oliver@apple.com75f804e2013-03-07 00:25:20 +0000670
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000671 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000672 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident);
673 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000674 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
oliver@apple.com58c86752013-07-25 04:02:40 +0000675 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000676 return oldValue.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000677}
678
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000679RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000680{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000681 if (dst == generator.ignoredResult())
682 return PrefixNode::emitBracket(generator, dst);
683
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000684 ASSERT(m_expr->isBracketAccessorNode());
685 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
686 ExpressionNode* baseNode = bracketAccessor->base();
687 ExpressionNode* subscript = bracketAccessor->subscript();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000688
barraclough@apple.come3aa3f52012-09-06 00:55:46 +0000689 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000690 RefPtr<RegisterID> property = generator.emitNode(subscript);
691
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000692 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000693 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000694 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000695 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000696 generator.emitPutByVal(base.get(), property.get(), value.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000697 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000698}
699
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000700RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000701{
ggaren@apple.com20c0b6c2013-04-04 18:31:37 +0000702 if (dst == generator.ignoredResult())
703 return PrefixNode::emitDot(generator, dst);
704
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000705 ASSERT(m_expr->isDotAccessorNode());
706 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
707 ExpressionNode* baseNode = dotAccessor->base();
708 const Identifier& ident = dotAccessor->identifier();
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000709
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000710 RefPtr<RegisterID> base = generator.emitNode(baseNode);
711
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000712 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000713 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000714 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000715 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000716 generator.emitPutById(base.get(), ident, value.get());
barraclough@apple.com9b6b67b2012-09-06 02:02:54 +0000717 return generator.moveToDestinationIfNeeded(dst, oldValue);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000718}
719
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000720RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000721{
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000722 if (m_expr->isResolveNode())
723 return emitResolve(generator, dst);
724
725 if (m_expr->isBracketAccessorNode())
726 return emitBracket(generator, dst);
727
728 if (m_expr->isDotAccessorNode())
729 return emitDot(generator, dst);
730
barraclough@apple.com4920ae92010-11-12 03:06:07 +0000731 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000732 ? "Postfix ++ operator applied to value that is not a reference."
733 : "Postfix -- operator applied to value that is not a reference.");
734}
735
736// ------------------------------ DeleteResolveNode -----------------------------------
737
738RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
739{
oliver@apple.com58c86752013-07-25 04:02:40 +0000740 if (generator.local(m_ident).get())
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000741 return generator.emitLoad(generator.finalDestination(dst), false);
742
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000743 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000744 RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
745 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000746}
747
748// ------------------------------ DeleteBracketNode -----------------------------------
749
750RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
751{
752 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
753 RegisterID* r1 = generator.emitNode(m_subscript);
754
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000755 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000756 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
757}
758
759// ------------------------------ DeleteDotNode -----------------------------------
760
761RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
762{
763 RegisterID* r0 = generator.emitNode(m_base);
764
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000765 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000766 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
767}
768
769// ------------------------------ DeleteValueNode -----------------------------------
770
771RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
772{
773 generator.emitNode(generator.ignoredResult(), m_expr);
774
775 // delete on a non-location expression ignores the value and returns true
776 return generator.emitLoad(generator.finalDestination(dst), true);
777}
778
779// ------------------------------ VoidNode -------------------------------------
780
781RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
782{
783 if (dst == generator.ignoredResult()) {
784 generator.emitNode(generator.ignoredResult(), m_expr);
785 return 0;
786 }
787 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
788 return generator.emitLoad(dst, jsUndefined());
789}
790
791// ------------------------------ TypeOfValueNode -----------------------------------
792
793RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
794{
oliver@apple.com58c86752013-07-25 04:02:40 +0000795 if (Local local = generator.local(m_ident)) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000796 if (dst == generator.ignoredResult())
797 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +0000798 return generator.emitTypeOf(generator.finalDestination(dst), local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000799 }
800
oliver@apple.com58c86752013-07-25 04:02:40 +0000801 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
802 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000803 if (dst == generator.ignoredResult())
804 return 0;
oliver@apple.com58c86752013-07-25 04:02:40 +0000805 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000806}
807
808// ------------------------------ TypeOfValueNode -----------------------------------
809
810RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
811{
812 if (dst == generator.ignoredResult()) {
813 generator.emitNode(generator.ignoredResult(), m_expr);
814 return 0;
815 }
816 RefPtr<RegisterID> src = generator.emitNode(m_expr);
817 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
818}
819
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000820// ------------------------------ PrefixNode ----------------------------------
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000821
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000822RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000823{
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000824 ASSERT(m_expr->isResolveNode());
825 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
826 const Identifier& ident = resolve->identifier();
827
oliver@apple.com58c86752013-07-25 04:02:40 +0000828 if (Local local = generator.local(ident)) {
829 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +0000830 generator.emitReadOnlyExceptionIfNeeded();
oliver@apple.com58c86752013-07-25 04:02:40 +0000831 local = Local(generator.emitMove(generator.tempDestination(dst), local.get()), 0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000832 }
ggaren@apple.comf3036112013-04-27 23:14:04 +0000833 emitIncOrDec(generator, local.get(), m_operator);
834 return generator.moveToDestinationIfNeeded(dst, local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000835 }
836
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000837 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +0000838 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident);
839 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
840 emitIncOrDec(generator, value.get(), m_operator);
841 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
842 return generator.moveToDestinationIfNeeded(dst, value.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000843}
844
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000845RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000846{
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000847 ASSERT(m_expr->isBracketAccessorNode());
848 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
849 ExpressionNode* baseNode = bracketAccessor->base();
850 ExpressionNode* subscript = bracketAccessor->subscript();
851
barraclough@apple.come3aa3f52012-09-06 00:55:46 +0000852 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000853 RefPtr<RegisterID> property = generator.emitNode(subscript);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000854 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
855
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000856 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000857 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
ggaren@apple.comf3036112013-04-27 23:14:04 +0000858 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000859 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000860 generator.emitPutByVal(base.get(), property.get(), value);
861 return generator.moveToDestinationIfNeeded(dst, propDst.get());
862}
863
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000864RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000865{
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000866 ASSERT(m_expr->isDotAccessorNode());
867 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
868 ExpressionNode* baseNode = dotAccessor->base();
869 const Identifier& ident = dotAccessor->identifier();
870
871 RefPtr<RegisterID> base = generator.emitNode(baseNode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000872 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
873
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000874 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000875 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
ggaren@apple.comf3036112013-04-27 23:14:04 +0000876 emitIncOrDec(generator, value, m_operator);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000877 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000878 generator.emitPutById(base.get(), ident, value);
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000879 return generator.moveToDestinationIfNeeded(dst, propDst.get());
880}
881
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000882RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000883{
barraclough@apple.comff7867a2012-09-05 23:00:29 +0000884 if (m_expr->isResolveNode())
885 return emitResolve(generator, dst);
886
887 if (m_expr->isBracketAccessorNode())
888 return emitBracket(generator, dst);
889
890 if (m_expr->isDotAccessorNode())
891 return emitDot(generator, dst);
892
barraclough@apple.com4920ae92010-11-12 03:06:07 +0000893 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000894 ? "Prefix ++ operator applied to value that is not a reference."
895 : "Prefix -- operator applied to value that is not a reference.");
896}
897
898// ------------------------------ Unary Operation Nodes -----------------------------------
899
900RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
901{
902 RegisterID* src = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +0000903 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000904 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
905}
906
barraclough@apple.coma6bdfc82012-02-27 18:26:23 +0000907// ------------------------------ BitwiseNotNode -----------------------------------
908
909RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
910{
911 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
912 RegisterID* src1 = generator.emitNode(m_expr);
913 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
914}
915
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000916// ------------------------------ LogicalNotNode -----------------------------------
917
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +0000918void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000919{
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000920 // reverse the true and false targets
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +0000921 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
mjs@apple.comaed3cef2009-12-09 01:29:52 +0000922}
923
924
925// ------------------------------ Binary Operation Nodes -----------------------------------
926
927// BinaryOpNode::emitStrcat:
928//
929// This node generates an op_strcat operation. This opcode can handle concatenation of three or
930// more values, where we can determine a set of separate op_add operations would be operating on
931// string values.
932//
933// This function expects to be operating on a graph of AST nodes looking something like this:
934//
935// (a)... (b)
936// \ /
937// (+) (c)
938// \ /
939// [d] ((+))
940// \ /
941// [+=]
942//
943// The assignment operation is optional, if it exists the register holding the value on the
944// lefthand side of the assignment should be passing as the optional 'lhs' argument.
945//
946// The method should be called on the node at the root of the tree of regular binary add
947// operations (marked in the diagram with a double set of parentheses). This node must
948// be performing a string concatenation (determined by statically detecting that at least
949// one child must be a string).
950//
951// Since the minimum number of values being concatenated together is expected to be 3, if
952// a lhs to a concatenating assignment is not provided then the root add should have at
953// least one left child that is also an add that can be determined to be operating on strings.
954//
955RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
956{
957 ASSERT(isAdd());
958 ASSERT(resultDescriptor().definitelyIsString());
959
960 // Create a list of expressions for all the adds in the tree of nodes we can convert into
961 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
962 // added first, and the leftmost child is never added, so the vector produced for the
963 // example above will be [ c, b ].
964 Vector<ExpressionNode*, 16> reverseExpressionList;
965 reverseExpressionList.append(m_expr2);
966
967 // Examine the left child of the add. So long as this is a string add, add its right-child
968 // to the list, and keep processing along the left fork.
969 ExpressionNode* leftMostAddChild = m_expr1;
970 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
971 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
972 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
973 }
974
975 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
976
977 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
978 // We could possibly avoid this (the lhs is converted last anyway, we could let the
979 // op_strcat node handle its conversion if required).
980 if (lhs)
981 temporaryRegisters.append(generator.newTemporary());
982
983 // Emit code for the leftmost node ((a) in the example).
984 temporaryRegisters.append(generator.newTemporary());
985 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
986 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
987
988 // Note on ordering of conversions:
989 //
990 // We maintain the same ordering of conversions as we would see if the concatenations
991 // was performed as a sequence of adds (otherwise this optimization could change
992 // behaviour should an object have been provided a valueOf or toString method).
993 //
994 // Considering the above example, the sequnce of execution is:
995 // * evaluate operand (a)
996 // * evaluate operand (b)
997 // * convert (a) to primitive <- (this would be triggered by the first add)
998 // * convert (b) to primitive <- (ditto)
999 // * evaluate operand (c)
1000 // * convert (c) to primitive <- (this would be triggered by the second add)
1001 // And optionally, if there is an assignment:
1002 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1003 //
1004 // As such we do not plant an op to convert the leftmost child now. Instead, use
1005 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1006 // once the second node has been generated. However, if the leftmost child is an
1007 // immediate we can trivially determine that no conversion will be required.
1008 // If this is the case
1009 if (leftMostAddChild->isString())
1010 leftMostAddChildTempRegister = 0;
1011
1012 while (reverseExpressionList.size()) {
1013 ExpressionNode* node = reverseExpressionList.last();
1014 reverseExpressionList.removeLast();
1015
1016 // Emit the code for the current node.
1017 temporaryRegisters.append(generator.newTemporary());
1018 generator.emitNode(temporaryRegisters.last().get(), node);
1019
1020 // On the first iteration of this loop, when we first reach this point we have just
1021 // generated the second node, which means it is time to convert the leftmost operand.
1022 if (leftMostAddChildTempRegister) {
1023 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1024 leftMostAddChildTempRegister = 0; // Only do this once.
1025 }
1026 // Plant a conversion for this node, if necessary.
1027 if (!node->isString())
1028 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1029 }
1030 ASSERT(temporaryRegisters.size() >= 3);
1031
1032 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1033 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1034 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001035 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001036 // If there is an assignment convert the lhs now. This will also copy lhs to
1037 // the temporary register we allocated for it.
1038 if (lhs)
1039 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1040
1041 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1042}
1043
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001044void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1045{
1046 TriState branchCondition;
1047 ExpressionNode* branchExpression;
1048 tryFoldToBranch(generator, branchCondition, branchExpression);
1049
1050 if (branchCondition == MixedTriState)
1051 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1052 else if (branchCondition == TrueTriState)
1053 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1054 else
1055 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1056}
1057
1058static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1059{
1060 ResultType expressionType = branchExpression->resultDescriptor();
1061
1062 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1063 return true;
1064 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1065 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1066 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1067 return true;
1068
1069 return false;
1070}
1071
1072void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1073{
1074 branchCondition = MixedTriState;
1075 branchExpression = 0;
1076
1077 ConstantNode* constant = 0;
1078 if (m_expr1->isConstant()) {
1079 constant = static_cast<ConstantNode*>(m_expr1);
1080 branchExpression = m_expr2;
1081 } else if (m_expr2->isConstant()) {
1082 constant = static_cast<ConstantNode*>(m_expr2);
1083 branchExpression = m_expr1;
1084 }
1085
1086 if (!constant)
1087 return;
1088 ASSERT(branchExpression);
1089
1090 OpcodeID opcodeID = this->opcodeID();
1091 JSValue value = constant->jsValue(generator);
1092 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1093 if (!canFoldToBranch)
1094 return;
1095
1096 if (opcodeID == op_eq || opcodeID == op_stricteq)
1097 branchCondition = triState(value.pureToBoolean());
1098 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1099 branchCondition = triState(!value.pureToBoolean());
1100}
1101
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001102RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1103{
1104 OpcodeID opcodeID = this->opcodeID();
1105
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001106 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001107 generator.emitExpressionInfo(position(), position(), position());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001108 return emitStrcat(generator, dst);
mark.lam@apple.com0e3a6ac2013-07-24 00:56:52 +00001109 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001110
1111 if (opcodeID == op_neq) {
1112 if (m_expr1->isNull() || m_expr2->isNull()) {
1113 RefPtr<RegisterID> src = generator.tempDestination(dst);
1114 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1115 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1116 }
1117 }
1118
oliver@apple.comece74042012-12-01 00:50:39 +00001119 ExpressionNode* left = m_expr1;
1120 ExpressionNode* right = m_expr2;
1121 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1122 if (left->isString())
1123 std::swap(left, right);
1124 }
1125
1126 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
1127 bool wasTypeof = generator.m_lastOpcodeID == op_typeof;
1128 RegisterID* src2 = generator.emitNode(right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001129 generator.emitExpressionInfo(position(), position(), position());
oliver@apple.comece74042012-12-01 00:50:39 +00001130 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001131 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1132 if (opcodeID == op_neq)
1133 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1134 else if (opcodeID == op_nstricteq)
1135 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1136 else
oliver@apple.com5598c182013-01-23 22:25:07 +00001137 RELEASE_ASSERT_NOT_REACHED();
bfulgham@webkit.org31940df2012-11-14 19:26:04 +00001138 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1139 }
oliver@apple.comece74042012-12-01 00:50:39 +00001140 return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001141}
1142
1143RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1144{
1145 if (m_expr1->isNull() || m_expr2->isNull()) {
1146 RefPtr<RegisterID> src = generator.tempDestination(dst);
1147 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1148 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1149 }
1150
oliver@apple.comece74042012-12-01 00:50:39 +00001151 ExpressionNode* left = m_expr1;
1152 ExpressionNode* right = m_expr2;
1153 if (left->isString())
1154 std::swap(left, right);
1155
1156 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
1157 RegisterID* src2 = generator.emitNode(right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001158 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1159}
1160
1161RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1162{
oliver@apple.comece74042012-12-01 00:50:39 +00001163 ExpressionNode* left = m_expr1;
1164 ExpressionNode* right = m_expr2;
1165 if (left->isString())
1166 std::swap(left, right);
1167
1168 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
1169 RegisterID* src2 = generator.emitNode(right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001170 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1171}
1172
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001173RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1174{
1175 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1176 RegisterID* src2 = generator.emitNode(m_expr2);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001177 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001178 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1179}
1180
1181RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1182{
1183 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1184 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001185 RefPtr<RegisterID> prototype = generator.newTemporary();
1186 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1187 RefPtr<Label> target = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001188
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001189 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001190 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
barraclough@apple.com8da6d972010-11-16 21:11:26 +00001191
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001192 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +00001193 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001194
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001195 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
barraclough@apple.com094dbd92012-09-22 01:18:54 +00001196 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
barraclough@apple.comb46d57b42012-09-22 00:43:03 +00001197 generator.emitLabel(target.get());
1198 return result;
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001199}
1200
1201// ------------------------------ LogicalOpNode ----------------------------
1202
1203RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1204{
1205 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1206 RefPtr<Label> target = generator.newLabel();
1207
1208 generator.emitNode(temp.get(), m_expr1);
1209 if (m_operator == OpLogicalAnd)
1210 generator.emitJumpIfFalse(temp.get(), target.get());
1211 else
1212 generator.emitJumpIfTrue(temp.get(), target.get());
1213 generator.emitNode(temp.get(), m_expr2);
1214 generator.emitLabel(target.get());
1215
1216 return generator.moveToDestinationIfNeeded(dst, temp.get());
1217}
1218
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001219void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001220{
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001221 RefPtr<Label> afterExpr1 = generator.newLabel();
1222 if (m_operator == OpLogicalAnd)
1223 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1224 else
1225 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1226 generator.emitLabel(afterExpr1.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001227
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001228 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001229}
1230
1231// ------------------------------ ConditionalNode ------------------------------
1232
1233RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1234{
1235 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1236 RefPtr<Label> beforeElse = generator.newLabel();
1237 RefPtr<Label> afterElse = generator.newLabel();
1238
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001239 RefPtr<Label> beforeThen = generator.newLabel();
1240 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1241 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001242
1243 generator.emitNode(newDst.get(), m_expr1);
1244 generator.emitJump(afterElse.get());
1245
1246 generator.emitLabel(beforeElse.get());
1247 generator.emitNode(newDst.get(), m_expr2);
1248
1249 generator.emitLabel(afterElse.get());
1250
1251 return newDst.get();
1252}
1253
1254// ------------------------------ ReadModifyResolveNode -----------------------------------
1255
1256// FIXME: should this be moved to be a method on BytecodeGenerator?
1257static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1258{
1259 OpcodeID opcodeID;
1260 switch (oper) {
1261 case OpMultEq:
1262 opcodeID = op_mul;
1263 break;
1264 case OpDivEq:
1265 opcodeID = op_div;
1266 break;
1267 case OpPlusEq:
1268 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1269 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1270 opcodeID = op_add;
1271 break;
1272 case OpMinusEq:
1273 opcodeID = op_sub;
1274 break;
1275 case OpLShift:
1276 opcodeID = op_lshift;
1277 break;
1278 case OpRShift:
1279 opcodeID = op_rshift;
1280 break;
1281 case OpURShift:
1282 opcodeID = op_urshift;
1283 break;
1284 case OpAndEq:
1285 opcodeID = op_bitand;
1286 break;
1287 case OpXOrEq:
1288 opcodeID = op_bitxor;
1289 break;
1290 case OpOrEq:
1291 opcodeID = op_bitor;
1292 break;
1293 case OpModEq:
1294 opcodeID = op_mod;
1295 break;
1296 default:
oliver@apple.com5598c182013-01-23 22:25:07 +00001297 RELEASE_ASSERT_NOT_REACHED();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001298 return dst;
1299 }
1300
1301 RegisterID* src2 = generator.emitNode(m_right);
1302
1303 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1304 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1305 if (emitExpressionInfoForMe)
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001306 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001307 return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1308}
1309
1310RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1311{
oliver@apple.com58c86752013-07-25 04:02:40 +00001312 if (Local local = generator.local(m_ident)) {
1313 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001314 generator.emitReadOnlyExceptionIfNeeded();
oliver@apple.com58c86752013-07-25 04:02:40 +00001315 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
ggaren@apple.com6e309822012-09-05 21:44:43 +00001316 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001317
1318 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1319 RefPtr<RegisterID> result = generator.newTemporary();
oliver@apple.com58c86752013-07-25 04:02:40 +00001320 generator.emitMove(result.get(), local.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001321 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
oliver@apple.com58c86752013-07-25 04:02:40 +00001322 generator.emitMove(local.get(), result.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001323 return generator.moveToDestinationIfNeeded(dst, result.get());
1324 }
1325
oliver@apple.com58c86752013-07-25 04:02:40 +00001326 RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001327 return generator.moveToDestinationIfNeeded(dst, result);
1328 }
1329
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001330 JSTextPosition newDivot = divotStart() + m_ident.length();
1331 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
oliver@apple.com58c86752013-07-25 04:02:40 +00001332 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1333 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound);
1334 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
1335 return generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001336}
1337
1338// ------------------------------ AssignResolveNode -----------------------------------
1339
1340RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1341{
oliver@apple.com58c86752013-07-25 04:02:40 +00001342 if (Local local = generator.local(m_ident)) {
1343 if (local.isReadOnly()) {
ggaren@apple.com6e309822012-09-05 21:44:43 +00001344 generator.emitReadOnlyExceptionIfNeeded();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001345 return generator.emitNode(dst, m_right);
ggaren@apple.com6e309822012-09-05 21:44:43 +00001346 }
oliver@apple.com58c86752013-07-25 04:02:40 +00001347 RegisterID* result = generator.emitNode(local.get(), m_right);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001348 return generator.moveToDestinationIfNeeded(dst, result);
1349 }
1350
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001351 if (generator.isStrictMode())
1352 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +00001353 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001354 if (dst == generator.ignoredResult())
1355 dst = 0;
oliver@apple.com58c86752013-07-25 04:02:40 +00001356 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001357 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +00001358 return generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001359}
1360
1361// ------------------------------ AssignDotNode -----------------------------------
1362
1363RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1364{
1365 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1366 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1367 RegisterID* result = generator.emitNode(value.get(), m_right);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001368 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001369 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1370 generator.emitPutById(base.get(), m_ident, forwardResult);
1371 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001372}
1373
1374// ------------------------------ ReadModifyDotNode -----------------------------------
1375
1376RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1377{
1378 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1379
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001380 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001381 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1382 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1383
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001384 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001385 return generator.emitPutById(base.get(), m_ident, updatedValue);
1386}
1387
1388// ------------------------------ AssignErrorNode -----------------------------------
1389
1390RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1391{
barraclough@apple.com4920ae92010-11-12 03:06:07 +00001392 return emitThrowReferenceError(generator, "Left side of assignment is not a reference.");
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001393}
1394
1395// ------------------------------ AssignBracketNode -----------------------------------
1396
1397RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1398{
1399 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1400 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1401 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1402 RegisterID* result = generator.emitNode(value.get(), m_right);
1403
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001404 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
commit-queue@webkit.org4f845d52011-10-21 09:11:26 +00001405 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1406 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1407 return generator.moveToDestinationIfNeeded(dst, forwardResult);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001408}
1409
1410// ------------------------------ ReadModifyBracketNode -----------------------------------
1411
1412RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1413{
1414 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1415 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1416
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001417 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001418 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1419 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1420
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001421 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001422 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1423
1424 return updatedValue;
1425}
1426
1427// ------------------------------ CommaNode ------------------------------------
1428
1429RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1430{
1431 ASSERT(m_expressions.size() > 1);
1432 for (size_t i = 0; i < m_expressions.size() - 1; i++)
1433 generator.emitNode(generator.ignoredResult(), m_expressions[i]);
1434 return generator.emitNode(dst, m_expressions.last());
1435}
1436
1437// ------------------------------ ConstDeclNode ------------------------------------
1438
1439RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1440{
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001441 // FIXME: This code does not match the behavior of const in Firefox.
oliver@apple.com58c86752013-07-25 04:02:40 +00001442 if (RegisterID* local = generator.constLocal(m_ident).get()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001443 if (!m_init)
1444 return local;
1445
1446 return generator.emitNode(local, m_init);
1447 }
1448
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001449 RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1450
oliver@apple.com75f804e2013-03-07 00:25:20 +00001451 if (generator.codeType() == GlobalCode)
1452 return generator.emitInitGlobalConst(m_ident, value.get());
1453
ggaren@apple.com829e3bb2011-06-21 23:39:28 +00001454 if (generator.codeType() != EvalCode)
1455 return value.get();
1456
oliver@apple.comc909f5f2012-10-18 23:37:40 +00001457 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
oliver@apple.com58c86752013-07-25 04:02:40 +00001458 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1459 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001460}
1461
1462RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1463{
1464 RegisterID* result = 0;
1465 for (ConstDeclNode* n = this; n; n = n->m_next)
1466 result = n->emitCodeSingle(generator);
1467
1468 return result;
1469}
1470
1471// ------------------------------ ConstStatementNode -----------------------------
1472
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001473void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001474{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001475 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001476 generator.emitNode(m_next);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001477}
1478
1479// ------------------------------ SourceElements -------------------------------
1480
1481
1482inline StatementNode* SourceElements::lastStatement() const
1483{
1484 size_t size = m_statements.size();
1485 return size ? m_statements[size - 1] : 0;
1486}
1487
1488inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1489{
1490 size_t size = m_statements.size();
1491 for (size_t i = 0; i < size; ++i)
1492 generator.emitNode(dst, m_statements[i]);
1493}
1494
1495// ------------------------------ BlockNode ------------------------------------
1496
1497inline StatementNode* BlockNode::lastStatement() const
1498{
1499 return m_statements ? m_statements->lastStatement() : 0;
1500}
1501
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00001502inline StatementNode* BlockNode::singleStatement() const
1503{
1504 return m_statements ? m_statements->singleStatement() : 0;
1505}
1506
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001507void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001508{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001509 if (!m_statements)
1510 return;
1511 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001512}
1513
1514// ------------------------------ EmptyStatementNode ---------------------------
1515
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001516void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001517{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001518 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001519}
1520
1521// ------------------------------ DebuggerStatementNode ---------------------------
1522
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001523void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001524{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001525 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001526}
1527
1528// ------------------------------ ExprStatementNode ----------------------------
1529
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001530void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001531{
1532 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001533 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001534 generator.emitNode(dst, m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001535}
1536
1537// ------------------------------ VarStatementNode ----------------------------
1538
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001539void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001540{
1541 ASSERT(m_expr);
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001542 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001543 generator.emitNode(m_expr);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001544}
1545
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001546// ------------------------------ IfElseNode ---------------------------------------
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001547
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001548static inline StatementNode* singleStatement(StatementNode* statementNode)
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001549{
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001550 if (statementNode->isBlock())
1551 return static_cast<BlockNode*>(statementNode)->singleStatement();
1552 return statementNode;
fpizlo@apple.com335ba392013-04-26 00:40:27 +00001553}
1554
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001555bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
1556 Label*& trueTarget, FallThroughMode& fallThroughMode)
1557{
1558 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
1559 if (!singleStatement)
1560 return false;
1561
1562 if (singleStatement->isBreak()) {
1563 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
1564 Label* target = breakNode->trivialTarget(generator);
1565 if (!target)
1566 return false;
1567 trueTarget = target;
1568 fallThroughMode = FallThroughMeansFalse;
1569 return true;
1570 }
1571
1572 if (singleStatement->isContinue()) {
1573 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
1574 Label* target = continueNode->trivialTarget(generator);
1575 if (!target)
1576 return false;
1577 trueTarget = target;
1578 fallThroughMode = FallThroughMeansFalse;
1579 return true;
1580 }
1581
1582 return false;
1583}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001584
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001585void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001586{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001587 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001588
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001589 RefPtr<Label> beforeThen = generator.newLabel();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001590 RefPtr<Label> beforeElse = generator.newLabel();
1591 RefPtr<Label> afterElse = generator.newLabel();
1592
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001593 Label* trueTarget = beforeThen.get();
1594 Label* falseTarget = beforeElse.get();
1595 FallThroughMode fallThroughMode = FallThroughMeansTrue;
1596 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
1597
1598 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001599 generator.emitLabel(beforeThen.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001600
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001601 if (!didFoldIfBlock) {
1602 generator.emitNode(dst, m_ifBlock);
1603 if (m_elseBlock)
1604 generator.emitJump(afterElse.get());
1605 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001606
1607 generator.emitLabel(beforeElse.get());
1608
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001609 if (m_elseBlock)
1610 generator.emitNode(dst, m_elseBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001611
1612 generator.emitLabel(afterElse.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001613}
1614
1615// ------------------------------ DoWhileNode ----------------------------------
1616
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001617void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001618{
oliver@apple.com6a976452013-03-11 21:02:39 +00001619 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001620
1621 RefPtr<Label> topOfLoop = generator.newLabel();
1622 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001623 generator.emitLoopHint();
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001624 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
commit-queue@webkit.org1b331cb2012-08-06 03:16:46 +00001625
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001626 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001627
1628 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001629 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001630 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001631
1632 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001633}
1634
1635// ------------------------------ WhileNode ------------------------------------
1636
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001637void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001638{
oliver@apple.com6a976452013-03-11 21:02:39 +00001639 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001640 RefPtr<Label> topOfLoop = generator.newLabel();
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001641
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001642 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->startOffset(), m_expr->lineStartOffset());
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001643 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001644
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001645 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001646 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001647
1648 generator.emitNode(dst, m_statement);
1649
1650 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001651 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001652
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001653 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001654
1655 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001656}
1657
1658// ------------------------------ ForNode --------------------------------------
1659
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001660void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001661{
oliver@apple.com6a976452013-03-11 21:02:39 +00001662 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001663
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001664 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001665
1666 if (m_expr1)
1667 generator.emitNode(generator.ignoredResult(), m_expr1);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001668
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001669 RefPtr<Label> topOfLoop = generator.newLabel();
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001670 if (m_expr2)
1671 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
fpizlo@apple.comda27d042012-05-20 10:00:08 +00001672
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001673 generator.emitLabel(topOfLoop.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001674 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001675
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001676 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001677
1678 generator.emitLabel(scope->continueTarget());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001679 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001680 if (m_expr3)
1681 generator.emitNode(generator.ignoredResult(), m_expr3);
1682
ggaren@apple.comd7cf35d2013-03-29 19:12:18 +00001683 if (m_expr2)
1684 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1685 else
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001686 generator.emitJump(topOfLoop.get());
1687
1688 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001689}
1690
1691// ------------------------------ ForInNode ------------------------------------
1692
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001693void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001694{
oliver@apple.com6a976452013-03-11 21:02:39 +00001695 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001696
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001697 if (!m_lexpr->isLocation()) {
1698 emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
1699 return;
1700 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001701
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001702 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001703
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001704 RefPtr<RegisterID> base = generator.newTemporary();
1705 generator.emitNode(base.get(), m_expr);
1706 RefPtr<RegisterID> i = generator.newTemporary();
1707 RefPtr<RegisterID> size = generator.newTemporary();
1708 RefPtr<RegisterID> expectedSubscript;
1709 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
1710 generator.emitJump(scope->continueTarget());
1711
1712 RefPtr<Label> loopStart = generator.newLabel();
1713 generator.emitLabel(loopStart.get());
fpizlo@apple.coma71ab052011-09-13 05:35:53 +00001714 generator.emitLoopHint();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001715
1716 RegisterID* propertyName;
1717 bool optimizedForinAccess = false;
1718 if (m_lexpr->isResolveNode()) {
1719 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
oliver@apple.com58c86752013-07-25 04:02:40 +00001720 Local local = generator.local(ident);
1721 propertyName = local.get();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001722 if (!propertyName) {
1723 propertyName = generator.newTemporary();
1724 RefPtr<RegisterID> protect = propertyName;
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001725 if (generator.isStrictMode())
1726 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +00001727 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001728 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com58c86752013-07-25 04:02:40 +00001729 generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001730 } else {
1731 expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
1732 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
1733 optimizedForinAccess = true;
1734 }
1735 } else if (m_lexpr->isDotAccessorNode()) {
1736 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1737 const Identifier& ident = assignNode->identifier();
1738 propertyName = generator.newTemporary();
1739 RefPtr<RegisterID> protect = propertyName;
1740 RegisterID* base = generator.emitNode(assignNode->base());
1741
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001742 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001743 generator.emitPutById(base, ident, propertyName);
oliver@apple.comd055db62013-10-02 19:11:04 +00001744 } else if (m_lexpr->isBracketAccessorNode()) {
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001745 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1746 propertyName = generator.newTemporary();
1747 RefPtr<RegisterID> protect = propertyName;
1748 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1749 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1750
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001751 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001752 generator.emitPutByVal(base.get(), subscript, propertyName);
oliver@apple.comd055db62013-10-02 19:11:04 +00001753 } else {
1754 ASSERT(m_lexpr->isDeconstructionNode());
1755 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
1756 auto binding = assignNode->bindings();
1757 if (binding->isBindingNode()) {
1758 auto simpleBinding = static_cast<BindingNode*>(binding);
1759 Identifier ident = simpleBinding->boundProperty();
1760 Local local = generator.local(ident);
1761 propertyName = local.get();
1762 if (!propertyName)
1763 goto genericBinding;
1764 expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
1765 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
1766 optimizedForinAccess = true;
1767 goto completedSimpleBinding;
1768 } else {
1769 genericBinding:
1770 propertyName = generator.newTemporary();
1771 RefPtr<RegisterID> protect(propertyName);
1772 assignNode->bindings()->emitBytecode(generator, propertyName);
1773 }
1774 completedSimpleBinding:
1775 ;
1776 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001777
1778 generator.emitNode(dst, m_statement);
1779
1780 if (optimizedForinAccess)
1781 generator.popOptimisedForIn();
1782
1783 generator.emitLabel(scope->continueTarget());
1784 generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001785 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001786 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001787}
1788
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001789// ------------------------------ ForOfNode ------------------------------------
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001790void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1791{
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001792 if (!m_lexpr->isLocation()) {
1793 emitThrowReferenceError(generator, "Left side of for-of statement is not a reference.");
1794 return;
1795 }
1796
oliver@apple.com72f8a822013-10-17 01:02:34 +00001797 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1798
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001799 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
oliver@apple.com72f8a822013-10-17 01:02:34 +00001800 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001801 {
oliver@apple.com72f8a822013-10-17 01:02:34 +00001802 if (m_lexpr->isResolveNode()) {
1803 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1804 if (Local local = generator.local(ident))
1805 generator.emitMove(local.get(), value);
1806 else {
1807 if (generator.isStrictMode())
1808 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1809 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001810 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
oliver@apple.com72f8a822013-10-17 01:02:34 +00001811 generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
1812 }
1813 } else if (m_lexpr->isDotAccessorNode()) {
1814 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1815 const Identifier& ident = assignNode->identifier();
1816 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1817
1818 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1819 generator.emitPutById(base.get(), ident, value);
1820 } else if (m_lexpr->isBracketAccessorNode()) {
1821 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1822 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1823 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1824
1825 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1826 generator.emitPutByVal(base.get(), subscript, value);
1827 } else {
1828 ASSERT(m_lexpr->isDeconstructionNode());
1829 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
1830 assignNode->bindings()->emitBytecode(generator, value);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001831 }
oliver@apple.com72f8a822013-10-17 01:02:34 +00001832 generator.emitNode(dst, m_statement);
1833 };
1834 generator.emitEnumeration(this, m_expr, extractor);
oliver@apple.com20a9bf02013-10-04 20:35:24 +00001835}
1836
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001837// ------------------------------ ContinueNode ---------------------------------
1838
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001839Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
1840{
1841 if (generator.shouldEmitDebugHooks())
1842 return 0;
1843
1844 LabelScope* scope = generator.continueTarget(m_ident);
1845 ASSERT(scope);
1846
1847 if (generator.scopeDepth() != scope->scopeDepth())
1848 return 0;
1849
1850 return scope->continueTarget();
1851}
1852
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001853void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001854{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001855 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001856
1857 LabelScope* scope = generator.continueTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00001858 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001859
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00001860 generator.emitPopScopes(scope->scopeDepth());
1861 generator.emitJump(scope->continueTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001862}
1863
1864// ------------------------------ BreakNode ------------------------------------
1865
ggaren@apple.com81c68cc2013-04-27 06:43:33 +00001866Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
1867{
1868 if (generator.shouldEmitDebugHooks())
1869 return 0;
1870
1871 LabelScope* scope = generator.breakTarget(m_ident);
1872 ASSERT(scope);
1873
1874 if (generator.scopeDepth() != scope->scopeDepth())
1875 return 0;
1876
1877 return scope->breakTarget();
1878}
1879
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001880void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001881{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001882 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001883
1884 LabelScope* scope = generator.breakTarget(m_ident);
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00001885 ASSERT(scope);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001886
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00001887 generator.emitPopScopes(scope->scopeDepth());
1888 generator.emitJump(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001889}
1890
1891// ------------------------------ ReturnNode -----------------------------------
1892
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001893void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001894{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001895 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00001896 ASSERT(generator.codeType() == FunctionCode);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001897
1898 if (dst == generator.ignoredResult())
1899 dst = 0;
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00001900
1901 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001902 if (generator.scopeDepth()) {
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00001903 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
1904 generator.emitPopScopes(0);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001905 }
ggaren@apple.comb4787ec2013-03-29 00:09:56 +00001906
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001907 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001908 generator.emitReturn(returnRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001909}
1910
1911// ------------------------------ WithNode -------------------------------------
1912
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001913void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001914{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00001915 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
ggaren@apple.com170d6f22012-09-02 21:27:23 +00001916
1917 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00001918 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
ggaren@apple.com170d6f22012-09-02 21:27:23 +00001919 generator.emitPushWithScope(scope.get());
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001920 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001921 generator.emitPopScope();
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001922}
1923
1924// ------------------------------ CaseClauseNode --------------------------------
1925
1926inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1927{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00001928 if (!m_statements)
1929 return;
1930 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001931}
1932
1933// ------------------------------ CaseBlockNode --------------------------------
1934
1935enum SwitchKind {
1936 SwitchUnset = 0,
1937 SwitchNumber = 1,
1938 SwitchString = 2,
1939 SwitchNeither = 3
1940};
1941
1942static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
1943{
1944 for (; list; list = list->getNext()) {
1945 ExpressionNode* clauseExpression = list->getClause()->expr();
1946 literalVector.append(clauseExpression);
1947 if (clauseExpression->isNumber()) {
1948 double value = static_cast<NumberNode*>(clauseExpression)->value();
1949 int32_t intVal = static_cast<int32_t>(value);
1950 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
1951 typeForTable = SwitchNeither;
1952 break;
1953 }
1954 if (intVal < min_num)
1955 min_num = intVal;
1956 if (intVal > max_num)
1957 max_num = intVal;
1958 typeForTable = SwitchNumber;
1959 continue;
1960 }
1961 if (clauseExpression->isString()) {
1962 if (typeForTable & ~SwitchString) {
1963 typeForTable = SwitchNeither;
1964 break;
1965 }
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +00001966 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
barraclough@apple.comc2527d62010-08-11 19:52:41 +00001967 if (singleCharacterSwitch &= value.length() == 1) {
msaboff@apple.comaeb7a4a2011-09-01 20:04:34 +00001968 int32_t intVal = value[0];
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001969 if (intVal < min_num)
1970 min_num = intVal;
1971 if (intVal > max_num)
1972 max_num = intVal;
1973 }
1974 typeForTable = SwitchString;
1975 continue;
1976 }
1977 typeForTable = SwitchNeither;
1978 break;
1979 }
1980}
ggaren@apple.com18bbb012013-01-30 05:43:47 +00001981
1982static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001983{
ggaren@apple.com18bbb012013-01-30 05:43:47 +00001984 size_t length = 0;
1985 for (ClauseListNode* node = list1; node; node = node->getNext())
1986 ++length;
1987 for (ClauseListNode* node = list2; node; node = node->getNext())
1988 ++length;
1989 return length;
1990}
1991
1992SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
1993{
1994 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
1995 return SwitchInfo::SwitchNone;
1996
mjs@apple.comaed3cef2009-12-09 01:29:52 +00001997 SwitchKind typeForTable = SwitchUnset;
1998 bool singleCharacterSwitch = true;
1999
2000 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2001 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2002
2003 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2004 return SwitchInfo::SwitchNone;
2005
2006 if (typeForTable == SwitchNumber) {
2007 int32_t range = max_num - min_num;
2008 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2009 return SwitchInfo::SwitchImmediate;
2010 return SwitchInfo::SwitchNone;
2011 }
2012
2013 ASSERT(typeForTable == SwitchString);
2014
2015 if (singleCharacterSwitch) {
2016 int32_t range = max_num - min_num;
2017 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2018 return SwitchInfo::SwitchCharacter;
2019 }
2020
2021 return SwitchInfo::SwitchString;
2022}
2023
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002024void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002025{
2026 RefPtr<Label> defaultLabel;
2027 Vector<RefPtr<Label>, 8> labelVector;
2028 Vector<ExpressionNode*, 8> literalVector;
2029 int32_t min_num = std::numeric_limits<int32_t>::max();
2030 int32_t max_num = std::numeric_limits<int32_t>::min();
ggaren@apple.com18bbb012013-01-30 05:43:47 +00002031 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002032
2033 if (switchType != SwitchInfo::SwitchNone) {
2034 // Prepare the various labels
2035 for (uint32_t i = 0; i < literalVector.size(); i++)
2036 labelVector.append(generator.newLabel());
2037 defaultLabel = generator.newLabel();
2038 generator.beginSwitch(switchExpression, switchType);
2039 } else {
2040 // Setup jumps
2041 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2042 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2043 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2044 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2045 labelVector.append(generator.newLabel());
2046 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2047 }
2048
2049 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2050 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2051 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2052 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2053 labelVector.append(generator.newLabel());
2054 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2055 }
2056 defaultLabel = generator.newLabel();
2057 generator.emitJump(defaultLabel.get());
2058 }
2059
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002060 size_t i = 0;
2061 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2062 generator.emitLabel(labelVector[i++].get());
2063 list->getClause()->emitBytecode(generator, dst);
2064 }
2065
2066 if (m_defaultClause) {
2067 generator.emitLabel(defaultLabel.get());
2068 m_defaultClause->emitBytecode(generator, dst);
2069 }
2070
2071 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2072 generator.emitLabel(labelVector[i++].get());
2073 list->getClause()->emitBytecode(generator, dst);
2074 }
2075 if (!m_defaultClause)
2076 generator.emitLabel(defaultLabel.get());
2077
2078 ASSERT(i == labelVector.size());
2079 if (switchType != SwitchInfo::SwitchNone) {
2080 ASSERT(labelVector.size() == literalVector.size());
2081 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2082 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002083}
2084
2085// ------------------------------ SwitchNode -----------------------------------
2086
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002087void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002088{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002089 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002090
oliver@apple.com6a976452013-03-11 21:02:39 +00002091 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002092
2093 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002094 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002095
2096 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002097}
2098
2099// ------------------------------ LabelNode ------------------------------------
2100
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002101void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002102{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002103 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002104
barraclough@apple.com7e6bd6d2011-01-10 20:20:15 +00002105 ASSERT(!generator.breakTarget(m_name));
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002106
oliver@apple.com6a976452013-03-11 21:02:39 +00002107 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002108 generator.emitNode(dst, m_statement);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002109
2110 generator.emitLabel(scope->breakTarget());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002111}
2112
2113// ------------------------------ ThrowNode ------------------------------------
2114
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002115void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002116{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002117 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002118
2119 if (dst == generator.ignoredResult())
2120 dst = 0;
2121 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
mark.lam@apple.com3b256ca2013-07-30 17:01:40 +00002122 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002123 generator.emitThrow(expr.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002124}
2125
2126// ------------------------------ TryNode --------------------------------------
2127
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002128void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002129{
2130 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2131 // optimizer knows they may be jumped to from anywhere.
2132
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002133 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002134
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002135 ASSERT(m_catchBlock || m_finallyBlock);
2136
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002137 RefPtr<Label> tryStartLabel = generator.newLabel();
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002138 generator.emitLabel(tryStartLabel.get());
2139
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002140 if (m_finallyBlock)
2141 generator.pushFinallyContext(m_finallyBlock);
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002142 TryData* tryData = generator.pushTry(tryStartLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002143
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002144 generator.emitNode(dst, m_tryBlock);
2145
2146 if (m_catchBlock) {
2147 RefPtr<Label> catchEndLabel = generator.newLabel();
2148
2149 // Normal path: jump over the catch block.
2150 generator.emitJump(catchEndLabel.get());
2151
2152 // Uncaught exception path: the catch block.
2153 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002154 RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
2155
2156 if (m_finallyBlock) {
2157 // If the catch block throws an exception and we have a finally block, then the finally
2158 // block should "catch" that exception.
2159 tryData = generator.pushTry(here.get());
2160 }
2161
ggaren@apple.com170d6f22012-09-02 21:27:23 +00002162 generator.emitPushNameScope(m_exceptionIdent, exceptionRegister.get(), DontDelete);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002163 generator.emitNode(dst, m_catchBlock);
2164 generator.emitPopScope();
2165 generator.emitLabel(catchEndLabel.get());
2166 }
2167
2168 if (m_finallyBlock) {
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002169 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2170
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002171 generator.popFinallyContext();
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002172
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002173 RefPtr<Label> finallyEndLabel = generator.newLabel();
2174
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002175 // Normal path: run the finally code, and jump to the end.
2176 generator.emitNode(dst, m_finallyBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002177 generator.emitJump(finallyEndLabel.get());
2178
2179 // Uncaught exception path: invoke the finally block, then re-throw the exception.
fpizlo@apple.comb08ed272012-08-27 00:49:25 +00002180 RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002181 generator.emitNode(dst, m_finallyBlock);
fpizlo@apple.comdd58bf92012-04-04 04:25:56 +00002182 generator.emitThrow(tempExceptionRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002183
2184 generator.emitLabel(finallyEndLabel.get());
2185 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002186}
2187
2188// ------------------------------ ScopeNode -----------------------------
2189
2190inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2191{
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002192 if (!m_statements)
2193 return;
2194 m_statements->emitBytecode(generator, dst);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002195}
2196
2197// ------------------------------ ProgramNode -----------------------------
2198
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002199void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002200{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002201 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002202
2203 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2204 generator.emitLoad(dstRegister.get(), jsUndefined());
2205 emitStatementsBytecode(generator, dstRegister.get());
2206
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002207 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002208 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002209}
2210
2211// ------------------------------ EvalNode -----------------------------
2212
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002213void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002214{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002215 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002216
2217 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2218 generator.emitLoad(dstRegister.get(), jsUndefined());
2219 emitStatementsBytecode(generator, dstRegister.get());
2220
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002221 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002222 generator.emitEnd(dstRegister.get());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002223}
2224
2225// ------------------------------ FunctionBodyNode -----------------------------
2226
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002227void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002228{
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002229 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002230 emitStatementsBytecode(generator, generator.ignoredResult());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002231
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002232 StatementNode* singleStatement = this->singleStatement();
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002233 ReturnNode* returnNode = 0;
2234
2235 // Check for a return statement at the end of a function composed of a single block.
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002236 if (singleStatement && singleStatement->isBlock()) {
2237 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2238 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002239 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002240 }
2241
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002242 // If there is no return we must automatically insert one.
2243 if (!returnNode) {
2244 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
mark.lam@apple.com5b45f902013-07-09 16:15:12 +00002245 ASSERT((startOffset() - 1) >= lineStartOffset());
mark.lam@apple.come72693d2013-09-24 23:52:57 +00002246 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset() - 1, lineStartOffset());
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002247 generator.emitReturn(r0);
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002248 return;
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002249 }
2250
2251 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
ggaren@apple.com7426f922010-07-16 04:58:30 +00002252 if (static_cast<BlockNode*>(singleStatement)->singleStatement()) {
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002253 ExpressionNode* returnValueExpression = returnNode->value();
2254 if (returnValueExpression && returnValueExpression->isSubtract()) {
2255 ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
2256 ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
ggaren@apple.com50c5ac22011-11-14 23:16:27 +00002257 if (lhsExpression->isResolveNode()
2258 && rhsExpression->isResolveNode()
2259 && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
2260 && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
2261
2262 generator.setIsNumericCompareFunction(true);
barraclough@apple.comb467c4c2010-07-13 20:34:11 +00002263 }
2264 }
2265 }
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002266}
2267
2268// ------------------------------ FuncDeclNode ---------------------------------
2269
ggaren@apple.comd786e6b2013-04-04 23:16:20 +00002270void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002271{
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002272}
2273
2274// ------------------------------ FuncExprNode ---------------------------------
2275
2276RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2277{
2278 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2279}
oliver@apple.comd055db62013-10-02 19:11:04 +00002280
2281// ------------------------------ DeconstructingAssignmentNode -----------------
2282RegisterID* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2283{
2284 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
2285 return result;
2286 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
2287 generator.emitNode(initializer.get(), m_initializer);
2288 m_bindings->emitBytecode(generator, initializer.get());
2289 return generator.moveToDestinationIfNeeded(dst, initializer.get());
2290}
2291
2292DeconstructionPatternNode::~DeconstructionPatternNode()
2293{
2294}
2295
2296void ArrayPatternNode::emitBytecode(BytecodeGenerator& generator, RegisterID* rhs) const
2297{
2298 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2299 auto target = m_targetPatterns[i];
2300 if (!target)
2301 continue;
2302 RefPtr<RegisterID> temp = generator.newTemporary();
2303 generator.emitLoad(temp.get(), jsNumber(i));
2304 generator.emitGetByVal(temp.get(), rhs, temp.get());
2305 target->emitBytecode(generator, temp.get());
2306 }
2307}
2308
2309RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
2310{
2311 if (rhs->isResolveNode()
2312 && generator.willResolveToArguments(static_cast<ResolveNode*>(rhs)->identifier())
2313 && !generator.symbolTable().slowArguments()) {
2314 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2315 auto target = m_targetPatterns[i];
2316 if (!target)
2317 continue;
2318
2319 RefPtr<RegisterID> temp = generator.newTemporary();
2320 generator.emitLoad(temp.get(), jsNumber(i));
2321 generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), temp.get());
2322 target->emitBytecode(generator, temp.get());
2323 }
2324 }
2325 if (!rhs->isSimpleArray())
2326 return 0;
2327 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
2328 Vector<ExpressionNode*> elements;
2329 for (; elementNodes; elementNodes = elementNodes->next())
2330 elements.append(elementNodes->value());
2331 if (m_targetPatterns.size() != elements.size())
2332 return 0;
2333 Vector<RefPtr<RegisterID>> registers;
2334 registers.reserveCapacity(m_targetPatterns.size());
2335 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2336 registers.uncheckedAppend(generator.newTemporary());
2337 generator.emitNode(registers.last().get(), elements[i]);
2338 }
2339
2340 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2341 if (m_targetPatterns[i])
2342 m_targetPatterns[i]->emitBytecode(generator, registers[i].get());
2343 }
2344 RefPtr<RegisterID> result = generator.finalDestination(dst);
2345 return generator.emitLoad(result.get(), jsUndefined());
2346}
2347
2348void ArrayPatternNode::toString(StringBuilder& builder) const
2349{
2350 builder.append('[');
2351 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2352 if (!m_targetPatterns[i]) {
2353 builder.append(',');
2354 continue;
2355 }
2356 m_targetPatterns[i]->toString(builder);
2357 if (i < m_targetPatterns.size() - 1)
2358 builder.append(',');
2359 }
2360 builder.append(']');
2361}
2362
2363void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2364{
2365 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2366 if (DeconstructionPatternNode* node = m_targetPatterns[i].get())
2367 node->collectBoundIdentifiers(identifiers);
2368 }
2369}
2370
2371void ObjectPatternNode::toString(StringBuilder& builder) const
2372{
2373 builder.append('{');
2374 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2375 if (m_targetPatterns[i].wasString) {
2376 builder.append('"');
2377 escapeStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
2378 builder.append('"');
2379 } else
2380 builder.append(m_targetPatterns[i].propertyName.string());
2381 builder.append(":");
2382 m_targetPatterns[i].pattern->toString(builder);
2383 if (i < m_targetPatterns.size() - 1)
2384 builder.append(',');
2385 }
2386 builder.append('}');
2387}
2388
2389void ObjectPatternNode::emitBytecode(BytecodeGenerator& generator, RegisterID* rhs) const
2390{
2391 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2392 auto& target = m_targetPatterns[i];
2393 RefPtr<RegisterID> temp = generator.newTemporary();
2394 generator.emitGetById(temp.get(), rhs, target.propertyName);
2395 target.pattern->emitBytecode(generator, temp.get());
2396 }
2397}
2398
2399void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2400{
2401 for (size_t i = 0; i < m_targetPatterns.size(); i++)
2402 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
2403}
2404
2405void BindingNode::emitBytecode(BytecodeGenerator& generator, RegisterID* value) const
2406{
2407 if (Local local = generator.local(m_boundProperty)) {
2408 if (local.isReadOnly()) {
2409 generator.emitReadOnlyExceptionIfNeeded();
2410 return;
2411 }
2412 generator.emitMove(local.get(), value);
2413 return;
2414 }
2415 if (generator.isStrictMode())
2416 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2417 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty);
2418 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2419 generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
2420 return;
2421}
2422
2423void BindingNode::toString(StringBuilder& builder) const
2424{
2425 builder.append(m_boundProperty.string());
2426}
2427
2428void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2429{
2430 identifiers.append(m_boundProperty);
2431}
oliver@apple.com72f8a822013-10-17 01:02:34 +00002432
2433RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2434{
2435 RELEASE_ASSERT_NOT_REACHED();
2436 return 0;
2437}
mjs@apple.comaed3cef2009-12-09 01:29:52 +00002438
2439} // namespace JSC