]> git.saurik.com Git - apple/javascriptcore.git/blame - bytecompiler/NodesCodegen.cpp
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / bytecompiler / NodesCodegen.cpp
CommitLineData
f9bf01c6
A
1/*
2* Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3* Copyright (C) 2001 Peter Kelly (pmk@post.com)
93a37866 4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
f9bf01c6
A
5* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
93a37866 8 * Copyright (C) 2012 Igalia, S.L.
f9bf01c6
A
9*
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
81345200 31#include "BuiltinNames.h"
f9bf01c6
A
32#include "BytecodeGenerator.h"
33#include "CallFrame.h"
34#include "Debugger.h"
35#include "JIT.h"
36#include "JSFunction.h"
37#include "JSGlobalObject.h"
93a37866 38#include "JSNameScope.h"
81345200 39#include "JSONObject.h"
f9bf01c6
A
40#include "LabelScope.h"
41#include "Lexer.h"
81345200 42#include "JSCInlines.h"
f9bf01c6
A
43#include "Parser.h"
44#include "PropertyNameArray.h"
4e4e5a6f 45#include "RegExpCache.h"
f9bf01c6
A
46#include "RegExpObject.h"
47#include "SamplingTool.h"
81345200 48#include "StackAlignment.h"
f9bf01c6
A
49#include <wtf/Assertions.h>
50#include <wtf/RefCountedLeakCounter.h>
51#include <wtf/Threading.h>
52
53using namespace WTF;
54
55namespace JSC {
56
57/*
58 Details of the emitBytecode function.
59
60 Return value: The register holding the production's value.
61 dst: An optional parameter specifying the most efficient destination at
62 which to store the production's value. The callee must honor dst.
63
64 The dst argument provides for a crude form of copy propagation. For example,
65
66 x = 1
67
68 becomes
69
70 load r[x], 1
71
72 instead of
73
74 load r0, 1
75 mov r[x], r0
76
77 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
78*/
79
93a37866
A
80void ExpressionNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
81{
82 RegisterID* result = generator.emitNode(this);
83 if (fallThroughMode == FallThroughMeansTrue)
84 generator.emitJumpIfFalse(result, falseTarget);
85 else
86 generator.emitJumpIfTrue(result, trueTarget);
87}
88
f9bf01c6
A
89// ------------------------------ ThrowableExpressionData --------------------------------
90
93a37866 91RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
f9bf01c6 92{
81345200 93 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
14957cd0
A
94 generator.emitThrowReferenceError(message);
95 return generator.newTemporary();
f9bf01c6
A
96}
97
93a37866 98// ------------------------------ ConstantNode ----------------------------------
f9bf01c6 99
93a37866 100void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
f9bf01c6 101{
93a37866
A
102 TriState value = jsValue(generator).pureToBoolean();
103 if (value == MixedTriState)
104 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
105 else if (value == TrueTriState && fallThroughMode == FallThroughMeansFalse)
106 generator.emitJump(trueTarget);
107 else if (value == FalseTriState && fallThroughMode == FallThroughMeansTrue)
108 generator.emitJump(falseTarget);
f9bf01c6 109
93a37866 110 // All other cases are unconditional fall-throughs, like "if (true)".
f9bf01c6
A
111}
112
93a37866 113RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6
A
114{
115 if (dst == generator.ignoredResult())
116 return 0;
93a37866 117 return generator.emitLoad(dst, jsValue(generator));
f9bf01c6
A
118}
119
93a37866 120JSValue StringNode::jsValue(BytecodeGenerator& generator) const
f9bf01c6 121{
93a37866 122 return generator.addStringConstant(m_value);
f9bf01c6
A
123}
124
125// ------------------------------ RegExpNode -----------------------------------
126
127RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
128{
f9bf01c6
A
129 if (dst == generator.ignoredResult())
130 return 0;
93a37866 131 return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string())));
f9bf01c6
A
132}
133
134// ------------------------------ ThisNode -------------------------------------
135
136RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
137{
138 if (dst == generator.ignoredResult())
139 return 0;
140 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
141}
142
143// ------------------------------ ResolveNode ----------------------------------
144
145bool ResolveNode::isPure(BytecodeGenerator& generator) const
146{
81345200 147 return generator.local(m_ident).get();
f9bf01c6
A
148}
149
150RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
151{
81345200 152 if (Local local = generator.local(m_ident)) {
f9bf01c6
A
153 if (dst == generator.ignoredResult())
154 return 0;
81345200 155 return generator.moveToDestinationIfNeeded(dst, local.get());
f9bf01c6
A
156 }
157
81345200
A
158 JSTextPosition divot = m_start + m_ident.length();
159 generator.emitExpressionInfo(divot, m_start, divot);
160 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
161 return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound);
f9bf01c6
A
162}
163
164// ------------------------------ ArrayNode ------------------------------------
165
166RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
167{
168 // FIXME: Should we put all of this code into emitNewArray?
169
170 unsigned length = 0;
171 ElementNode* firstPutElement;
172 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
81345200 173 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
f9bf01c6
A
174 break;
175 ++length;
176 }
177
178 if (!firstPutElement && !m_elision)
14957cd0 179 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
f9bf01c6 180
14957cd0 181 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
81345200
A
182 ElementNode* n = firstPutElement;
183 for (; n; n = n->next()) {
184 if (n->value()->isSpreadExpression())
185 goto handleSpread;
f9bf01c6
A
186 RegisterID* value = generator.emitNode(n->value());
187 length += n->elision();
188 generator.emitPutByIndex(array.get(), length++, value);
189 }
190
191 if (m_elision) {
14957cd0 192 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
f9bf01c6
A
193 generator.emitPutById(array.get(), generator.propertyNames().length, value);
194 }
195
196 return generator.moveToDestinationIfNeeded(dst, array.get());
81345200
A
197
198handleSpread:
199 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(length));
200 auto spreader = [this, array, index](BytecodeGenerator& generator, RegisterID* value)
201 {
202 generator.emitDirectPutByVal(array.get(), index.get(), value);
203 generator.emitInc(index.get());
204 };
205 for (; n; n = n->next()) {
206 if (n->elision())
207 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(n->elision())), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
208 if (n->value()->isSpreadExpression()) {
209 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(n->value());
210 generator.emitEnumeration(spread, spread->expression(), spreader);
211 } else {
212 generator.emitDirectPutByVal(array.get(), index.get(), generator.emitNode(n->value()));
213 generator.emitInc(index.get());
214 }
215 }
216
217 if (m_elision) {
218 generator.emitBinaryOp(op_add, index.get(), index.get(), generator.emitLoad(0, jsNumber(m_elision)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
219 generator.emitPutById(array.get(), generator.propertyNames().length, index.get());
220 }
221 return generator.moveToDestinationIfNeeded(dst, array.get());
f9bf01c6
A
222}
223
224bool ArrayNode::isSimpleArray() const
225{
226 if (m_elision || m_optional)
227 return false;
228 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
229 if (ptr->elision())
230 return false;
231 }
232 return true;
233}
234
93a37866 235ArgumentListNode* ArrayNode::toArgumentList(VM* vm, int lineNumber, int startPosition) const
f9bf01c6
A
236{
237 ASSERT(!m_elision && !m_optional);
238 ElementNode* ptr = m_element;
239 if (!ptr)
240 return 0;
93a37866
A
241 JSTokenLocation location;
242 location.line = lineNumber;
243 location.startOffset = startPosition;
244 ArgumentListNode* head = new (vm) ArgumentListNode(location, ptr->value());
f9bf01c6
A
245 ArgumentListNode* tail = head;
246 ptr = ptr->next();
247 for (; ptr; ptr = ptr->next()) {
248 ASSERT(!ptr->elision());
93a37866 249 tail = new (vm) ArgumentListNode(location, tail, ptr->value());
f9bf01c6
A
250 }
251 return head;
252}
253
254// ------------------------------ ObjectLiteralNode ----------------------------
255
256RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
257{
258 if (!m_list) {
259 if (dst == generator.ignoredResult())
260 return 0;
261 return generator.emitNewObject(generator.finalDestination(dst));
262 }
263 return generator.emitNode(dst, m_list);
264}
265
266// ------------------------------ PropertyListNode -----------------------------
267
268RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
269{
270 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
271
272 generator.emitNewObject(newObj.get());
273
6fe7ccc8
A
274 // Fast case: this loop just handles regular value properties.
275 PropertyListNode* p = this;
81345200
A
276 for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next) {
277 if (p->m_node->m_name) {
278 generator.emitDirectPutById(newObj.get(), *p->m_node->name(), generator.emitNode(p->m_node->m_assign));
279 continue;
280 }
281 RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression);
282 generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign));
283 }
6fe7ccc8
A
284
285 // Were there any get/set properties?
286 if (p) {
287 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
288 typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
289 GetterSetterMap map;
290
291 // Build a map, pairing get/set values together.
292 for (PropertyListNode* q = p; q; q = q->m_next) {
293 PropertyNode* node = q->m_node;
294 if (node->m_type == PropertyNode::Constant)
295 continue;
296
297 GetterSetterPair pair(node, static_cast<PropertyNode*>(0));
81345200 298 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
6fe7ccc8 299 if (!result.isNewEntry)
93a37866 300 result.iterator->value.second = node;
6fe7ccc8
A
301 }
302
303 // Iterate over the remaining properties in the list.
304 for (; p; p = p->m_next) {
305 PropertyNode* node = p->m_node;
6fe7ccc8
A
306
307 // Handle regular values.
308 if (node->m_type == PropertyNode::Constant) {
81345200
A
309 if (node->name()) {
310 generator.emitDirectPutById(newObj.get(), *node->name(), generator.emitNode(node->m_assign));
311 continue;
312 }
313 RefPtr<RegisterID> propertyName = generator.emitNode(p->m_node->m_expression);
314 generator.emitDirectPutByVal(newObj.get(), propertyName.get(), generator.emitNode(p->m_node->m_assign));
6fe7ccc8 315 continue;
f9bf01c6 316 }
81345200
A
317
318 RegisterID* value = generator.emitNode(node->m_assign);
6fe7ccc8
A
319
320 // This is a get/set property, find its entry in the map.
321 ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
81345200 322 GetterSetterMap::iterator it = map.find(node->name()->impl());
6fe7ccc8 323 ASSERT(it != map.end());
93a37866 324 GetterSetterPair& pair = it->value;
6fe7ccc8
A
325
326 // Was this already generated as a part of its partner?
327 if (pair.second == node)
328 continue;
329
330 // Generate the paired node now.
331 RefPtr<RegisterID> getterReg;
332 RefPtr<RegisterID> setterReg;
333
334 if (node->m_type == PropertyNode::Getter) {
335 getterReg = value;
336 if (pair.second) {
337 ASSERT(pair.second->m_type == PropertyNode::Setter);
338 setterReg = generator.emitNode(pair.second->m_assign);
339 } else {
340 setterReg = generator.newTemporary();
341 generator.emitLoad(setterReg.get(), jsUndefined());
342 }
343 } else {
344 ASSERT(node->m_type == PropertyNode::Setter);
345 setterReg = value;
346 if (pair.second) {
347 ASSERT(pair.second->m_type == PropertyNode::Getter);
348 getterReg = generator.emitNode(pair.second->m_assign);
349 } else {
350 getterReg = generator.newTemporary();
351 generator.emitLoad(getterReg.get(), jsUndefined());
352 }
f9bf01c6 353 }
6fe7ccc8 354
81345200 355 generator.emitPutGetterSetter(newObj.get(), *node->name(), getterReg.get(), setterReg.get());
f9bf01c6
A
356 }
357 }
6fe7ccc8 358
f9bf01c6
A
359 return generator.moveToDestinationIfNeeded(dst, newObj.get());
360}
361
362// ------------------------------ BracketAccessorNode --------------------------------
363
364RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
365{
93a37866
A
366 if (m_base->isResolveNode()
367 && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())
368 && !generator.symbolTable().slowArguments()) {
40a37d08 369 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
81345200 370 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
40a37d08 371 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property.get());
14957cd0
A
372 }
373
f9bf01c6
A
374 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
375 RegisterID* property = generator.emitNode(m_subscript);
81345200 376 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
f9bf01c6
A
377 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
378}
379
380// ------------------------------ DotAccessorNode --------------------------------
381
382RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
383{
14957cd0
A
384 if (m_ident == generator.propertyNames().length) {
385 if (!m_base->isResolveNode())
386 goto nonArgumentsPath;
387 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
388 if (!generator.willResolveToArguments(resolveNode->identifier()))
389 goto nonArgumentsPath;
81345200 390 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
14957cd0
A
391 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
392 }
393
394nonArgumentsPath:
40a37d08 395 RefPtr<RegisterID> base = generator.emitNode(m_base);
81345200 396 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
40a37d08 397 return generator.emitGetById(generator.finalDestination(dst), base.get(), m_ident);
f9bf01c6
A
398}
399
400// ------------------------------ ArgumentListNode -----------------------------
401
402RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
403{
404 ASSERT(m_expr);
405 return generator.emitNode(dst, m_expr);
406}
407
408// ------------------------------ NewExprNode ----------------------------------
409
410RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
411{
93a37866
A
412 ExpectedFunction expectedFunction;
413 if (m_expr->isResolveNode())
414 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
415 else
416 expectedFunction = NoExpectedFunction;
f9bf01c6 417 RefPtr<RegisterID> func = generator.emitNode(m_expr);
81345200 418 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
14957cd0 419 CallArguments callArguments(generator, m_args);
81345200 420 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
14957cd0
A
421}
422
81345200 423CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
14957cd0 424 : m_argumentsNode(argumentsNode)
81345200 425 , m_padding(0)
14957cd0
A
426{
427 if (generator.shouldEmitProfileHooks())
428 m_profileHookRegister = generator.newTemporary();
6fe7ccc8 429
81345200 430 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
14957cd0 431 if (argumentsNode) {
6fe7ccc8
A
432 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
433 ++argumentCountIncludingThis;
434 }
435
436 m_argv.grow(argumentCountIncludingThis);
437 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
438 m_argv[i] = generator.newTemporary();
81345200
A
439 ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() - 1);
440 }
441
442 while (stackOffset() % stackAlignmentRegisters()) {
443 m_argv.insert(0, generator.newTemporary());
444 m_padding++;
14957cd0 445 }
6fe7ccc8
A
446}
447
f9bf01c6
A
448// ------------------------------ EvalFunctionCallNode ----------------------------------
449
450RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
451{
81345200
A
452 if (Local local = generator.local(generator.propertyNames().eval)) {
453 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
454 CallArguments callArguments(generator, m_args);
455 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
456 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
457 }
458
459 RefPtr<RegisterID> func = generator.newTemporary();
14957cd0 460 CallArguments callArguments(generator, m_args);
81345200
A
461 JSTextPosition newDivot = divotStart() + 4;
462 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
463 generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval);
464 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound);
465 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStart(), divotEnd());
f9bf01c6
A
466}
467
468// ------------------------------ FunctionCallValueNode ----------------------------------
469
470RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
471{
472 RefPtr<RegisterID> func = generator.emitNode(m_expr);
81345200 473 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
14957cd0
A
474 CallArguments callArguments(generator, m_args);
475 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
81345200 476 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
f9bf01c6
A
477}
478
479// ------------------------------ FunctionCallResolveNode ----------------------------------
480
481RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
482{
93a37866 483 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
93a37866 484
81345200
A
485 if (Local local = generator.local(m_ident)) {
486 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get());
487 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
14957cd0
A
488 CallArguments callArguments(generator, m_args);
489 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
93a37866
A
490 // This passes NoExpectedFunction because we expect that if the function is in a
491 // local variable, then it's not one of our built-in constructors.
81345200 492 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
f9bf01c6
A
493 }
494
495 RefPtr<RegisterID> func = generator.newTemporary();
81345200 496 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
14957cd0 497 CallArguments callArguments(generator, m_args);
93a37866 498
81345200
A
499 JSTextPosition newDivot = divotStart() + m_ident.length();
500 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
501 generator.emitResolveScope(callArguments.thisRegister(), m_ident);
502 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound);
503 return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
f9bf01c6
A
504}
505
506// ------------------------------ FunctionCallBracketNode ----------------------------------
507
508RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
509{
510 RefPtr<RegisterID> base = generator.emitNode(m_base);
40a37d08 511 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
81345200 512 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
40a37d08 513 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
81345200 514 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
14957cd0
A
515 CallArguments callArguments(generator, m_args);
516 generator.emitMove(callArguments.thisRegister(), base.get());
81345200 517 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
f9bf01c6
A
518}
519
520// ------------------------------ FunctionCallDotNode ----------------------------------
521
522RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
523{
524 RefPtr<RegisterID> function = generator.tempDestination(dst);
81345200 525 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
14957cd0
A
526 CallArguments callArguments(generator, m_args);
527 generator.emitNode(callArguments.thisRegister(), m_base);
81345200 528 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
14957cd0 529 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
81345200
A
530 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
531}
532
533static RegisterID* getArgumentByVal(BytecodeGenerator& generator, ExpressionNode* base, RegisterID* property, RegisterID* dst, JSTextPosition divot, JSTextPosition divotStart, JSTextPosition divotEnd)
534{
535 if (base->isResolveNode()
536 && generator.willResolveToArguments(static_cast<ResolveNode*>(base)->identifier())
537 && !generator.symbolTable().slowArguments()) {
538 generator.emitExpressionInfo(divot, divotStart, divotEnd);
539 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
540 }
541 return nullptr;
f9bf01c6
A
542}
543
544RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
545{
546 RefPtr<Label> realCall = generator.newLabel();
547 RefPtr<Label> end = generator.newLabel();
548 RefPtr<RegisterID> base = generator.emitNode(m_base);
81345200
A
549 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
550 RefPtr<RegisterID> function;
551 bool emitCallCheck = !generator.isBuiltinFunction();
552 if (emitCallCheck) {
553 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
554 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
555 }
556 RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
f9bf01c6 557 {
81345200
A
558 if (m_args->m_listNode && m_args->m_listNode->m_expr && m_args->m_listNode->m_expr->isSpreadExpression()) {
559 RefPtr<RegisterID> profileHookRegister;
560 if (generator.shouldEmitProfileHooks())
561 profileHookRegister = generator.newTemporary();
562 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
563 ExpressionNode* subject = spread->expression();
564 RefPtr<RegisterID> thisRegister = getArgumentByVal(generator, subject, generator.emitLoad(0, jsNumber(0)), 0, spread->divot(), spread->divotStart(), spread->divotEnd());
565 RefPtr<RegisterID> argumentsRegister;
566 if (thisRegister)
567 argumentsRegister = generator.uncheckedRegisterForArguments();
568 else {
569 argumentsRegister = generator.emitNode(subject);
570 generator.emitExpressionInfo(spread->divot(), spread->divotStart(), spread->divotEnd());
571 thisRegister = generator.emitGetByVal(generator.newTemporary(), argumentsRegister.get(), generator.emitLoad(0, jsNumber(0)));
572 }
573 generator.emitCallVarargs(returnValue.get(), base.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 1, profileHookRegister.get(), divot(), divotStart(), divotEnd());
574 } else if (m_args->m_listNode && m_args->m_listNode->m_expr) {
14957cd0 575 ArgumentListNode* oldList = m_args->m_listNode;
f9bf01c6 576 m_args->m_listNode = m_args->m_listNode->m_next;
f9bf01c6 577
14957cd0
A
578 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
579 CallArguments callArguments(generator, m_args);
580 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
81345200 581 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
14957cd0 582 m_args->m_listNode = oldList;
14957cd0
A
583 } else {
584 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
585 CallArguments callArguments(generator, m_args);
586 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
81345200 587 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
14957cd0 588 }
f9bf01c6 589 }
81345200
A
590 if (emitCallCheck) {
591 generator.emitJump(end.get());
592 generator.emitLabel(realCall.get());
593 {
594 CallArguments callArguments(generator, m_args);
595 generator.emitMove(callArguments.thisRegister(), base.get());
596 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
597 }
598 generator.emitLabel(end.get());
f9bf01c6 599 }
81345200 600 return returnValue.get();
f9bf01c6 601}
14957cd0 602
f9bf01c6
A
603static bool areTrivialApplyArguments(ArgumentsNode* args)
604{
605 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
606 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
607}
608
609RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
610{
611 // A few simple cases can be trivially handled as ordinary function calls.
612 // function.apply(), function.apply(arg) -> identical to function.call
613 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
614 bool mayBeCall = areTrivialApplyArguments(m_args);
615
616 RefPtr<Label> realCall = generator.newLabel();
617 RefPtr<Label> end = generator.newLabel();
618 RefPtr<RegisterID> base = generator.emitNode(m_base);
81345200
A
619 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
620 RefPtr<RegisterID> function;
621 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
622 bool emitCallCheck = !generator.isBuiltinFunction();
623 if (emitCallCheck) {
624 function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
625 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
626 }
627 if (mayBeCall) {
628 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
629 ArgumentListNode* oldList = m_args->m_listNode;
630 if (m_args->m_listNode->m_expr->isSpreadExpression()) {
631 SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
632 RefPtr<RegisterID> profileHookRegister;
633 if (generator.shouldEmitProfileHooks())
634 profileHookRegister = generator.newTemporary();
635 RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
636 RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
637 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
638 RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
639
640 auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
641 {
642 RefPtr<Label> haveThis = generator.newLabel();
643 RefPtr<Label> end = generator.newLabel();
644 RefPtr<RegisterID> compareResult = generator.newTemporary();
645 RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
646 generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
647 generator.emitMove(thisRegister.get(), value);
648 generator.emitLoad(index.get(), jsNumber(1));
649 generator.emitJump(end.get());
650 generator.emitLabel(haveThis.get());
651 RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
652 generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
653 generator.emitMove(argumentsRegister.get(), value);
654 generator.emitLoad(index.get(), jsNumber(2));
655 generator.emitLabel(end.get());
656 };
657 generator.emitEnumeration(this, spread->expression(), extractor);
658 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
659 } else if (m_args->m_listNode->m_next) {
660 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
661 ASSERT(!m_args->m_listNode->m_next->m_next);
662 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.vm(), 0, 0);
663 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
664 CallArguments callArguments(generator, m_args);
665 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
666 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
14957cd0 667 } else {
81345200 668 m_args->m_listNode = m_args->m_listNode->m_next;
14957cd0
A
669 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
670 CallArguments callArguments(generator, m_args);
81345200
A
671 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
672 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
14957cd0 673 }
81345200 674 m_args->m_listNode = oldList;
f9bf01c6 675 } else {
6fe7ccc8 676 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
81345200
A
677 CallArguments callArguments(generator, m_args);
678 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
679 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
f9bf01c6 680 }
81345200
A
681 } else {
682 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
683 RefPtr<RegisterID> profileHookRegister;
684 if (generator.shouldEmitProfileHooks())
685 profileHookRegister = generator.newTemporary();
686 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
687 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
688 RefPtr<RegisterID> argsRegister;
689 ArgumentListNode* args = m_args->m_listNode->m_next;
690 if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()) && !generator.symbolTable().slowArguments())
691 argsRegister = generator.uncheckedRegisterForArguments();
692 else
693 argsRegister = generator.emitNode(args->m_expr);
694
695 // Function.prototype.apply ignores extra arguments, but we still
696 // need to evaluate them for side effects.
697 while ((args = args->m_next))
698 generator.emitNode(args->m_expr);
699
700 generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
f9bf01c6 701 }
81345200
A
702 if (emitCallCheck) {
703 generator.emitJump(end.get());
704 generator.emitLabel(realCall.get());
14957cd0
A
705 CallArguments callArguments(generator, m_args);
706 generator.emitMove(callArguments.thisRegister(), base.get());
81345200
A
707 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
708 generator.emitLabel(end.get());
f9bf01c6 709 }
81345200 710 return returnValue.get();
f9bf01c6
A
711}
712
93a37866 713// ------------------------------ PostfixNode ----------------------------------
f9bf01c6 714
93a37866 715static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
f9bf01c6 716{
93a37866 717 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
f9bf01c6
A
718}
719
720static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
721{
93a37866
A
722 if (dst == srcDst)
723 return generator.emitToNumber(generator.finalDestination(dst), srcDst);
724 RefPtr<RegisterID> tmp = generator.emitToNumber(generator.tempDestination(dst), srcDst);
725 emitIncOrDec(generator, srcDst, oper);
726 return generator.moveToDestinationIfNeeded(dst, tmp.get());
f9bf01c6
A
727}
728
93a37866 729RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 730{
93a37866
A
731 if (dst == generator.ignoredResult())
732 return PrefixNode::emitResolve(generator, dst);
f9bf01c6 733
93a37866
A
734 ASSERT(m_expr->isResolveNode());
735 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
736 const Identifier& ident = resolve->identifier();
f9bf01c6 737
81345200 738 if (Local local = generator.local(ident)) {
40a37d08 739 RefPtr<RegisterID> localReg = local.get();
81345200 740 if (local.isReadOnly()) {
93a37866 741 generator.emitReadOnlyExceptionIfNeeded();
40a37d08 742 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
81345200
A
743 } else if (local.isCaptured()) {
744 RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
745 ASSERT(dst != localReg);
746 RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
40a37d08
A
747 generator.emitToNumber(tempDst.get(), localReg.get());
748 generator.emitMove(tempDstSrc.get(), localReg.get());
81345200 749 emitIncOrDec(generator, tempDstSrc.get(), m_operator);
40a37d08 750 generator.emitMove(localReg.get(), tempDstSrc.get());
81345200 751 return tempDst.get();
f9bf01c6 752 }
40a37d08 753 return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
f9bf01c6 754 }
f9bf01c6 755
81345200
A
756 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
757 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident);
758 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
93a37866 759 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
81345200 760 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
93a37866
A
761 return oldValue.get();
762}
f9bf01c6 763
93a37866 764RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 765{
93a37866
A
766 if (dst == generator.ignoredResult())
767 return PrefixNode::emitBracket(generator, dst);
768
769 ASSERT(m_expr->isBracketAccessorNode());
770 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
771 ExpressionNode* baseNode = bracketAccessor->base();
772 ExpressionNode* subscript = bracketAccessor->subscript();
773
774 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
775 RefPtr<RegisterID> property = generator.emitNode(subscript);
f9bf01c6 776
81345200 777 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
f9bf01c6 778 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
93a37866 779 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
81345200 780 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
f9bf01c6 781 generator.emitPutByVal(base.get(), property.get(), value.get());
93a37866 782 return generator.moveToDestinationIfNeeded(dst, oldValue);
f9bf01c6
A
783}
784
93a37866 785RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 786{
93a37866
A
787 if (dst == generator.ignoredResult())
788 return PrefixNode::emitDot(generator, dst);
f9bf01c6 789
93a37866
A
790 ASSERT(m_expr->isDotAccessorNode());
791 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
792 ExpressionNode* baseNode = dotAccessor->base();
793 const Identifier& ident = dotAccessor->identifier();
794
795 RefPtr<RegisterID> base = generator.emitNode(baseNode);
f9bf01c6 796
81345200 797 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
93a37866
A
798 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
799 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
81345200 800 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
93a37866
A
801 generator.emitPutById(base.get(), ident, value.get());
802 return generator.moveToDestinationIfNeeded(dst, oldValue);
803}
f9bf01c6 804
93a37866 805RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 806{
93a37866
A
807 if (m_expr->isResolveNode())
808 return emitResolve(generator, dst);
809
810 if (m_expr->isBracketAccessorNode())
811 return emitBracket(generator, dst);
812
813 if (m_expr->isDotAccessorNode())
814 return emitDot(generator, dst);
815
14957cd0 816 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
f9bf01c6
A
817 ? "Postfix ++ operator applied to value that is not a reference."
818 : "Postfix -- operator applied to value that is not a reference.");
819}
820
821// ------------------------------ DeleteResolveNode -----------------------------------
822
823RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
824{
81345200 825 if (generator.local(m_ident).get())
f9bf01c6
A
826 return generator.emitLoad(generator.finalDestination(dst), false);
827
81345200
A
828 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
829 RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
830 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident);
f9bf01c6
A
831}
832
833// ------------------------------ DeleteBracketNode -----------------------------------
834
835RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
836{
837 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
40a37d08 838 RefPtr<RegisterID> r1 = generator.emitNode(m_subscript);
f9bf01c6 839
81345200 840 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
40a37d08 841 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
f9bf01c6
A
842}
843
844// ------------------------------ DeleteDotNode -----------------------------------
845
846RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
847{
40a37d08 848 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
f9bf01c6 849
81345200 850 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
40a37d08 851 return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
f9bf01c6
A
852}
853
854// ------------------------------ DeleteValueNode -----------------------------------
855
856RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
857{
858 generator.emitNode(generator.ignoredResult(), m_expr);
859
860 // delete on a non-location expression ignores the value and returns true
861 return generator.emitLoad(generator.finalDestination(dst), true);
862}
863
864// ------------------------------ VoidNode -------------------------------------
865
866RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
867{
868 if (dst == generator.ignoredResult()) {
869 generator.emitNode(generator.ignoredResult(), m_expr);
870 return 0;
871 }
872 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
873 return generator.emitLoad(dst, jsUndefined());
874}
875
876// ------------------------------ TypeOfValueNode -----------------------------------
877
878RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
879{
81345200 880 if (Local local = generator.local(m_ident)) {
f9bf01c6
A
881 if (dst == generator.ignoredResult())
882 return 0;
81345200 883 return generator.emitTypeOf(generator.finalDestination(dst), local.get());
93a37866
A
884 }
885
81345200
A
886 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
887 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
f9bf01c6
A
888 if (dst == generator.ignoredResult())
889 return 0;
81345200 890 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
f9bf01c6
A
891}
892
893// ------------------------------ TypeOfValueNode -----------------------------------
894
895RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
896{
897 if (dst == generator.ignoredResult()) {
898 generator.emitNode(generator.ignoredResult(), m_expr);
899 return 0;
900 }
901 RefPtr<RegisterID> src = generator.emitNode(m_expr);
902 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
903}
904
93a37866 905// ------------------------------ PrefixNode ----------------------------------
f9bf01c6 906
93a37866 907RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 908{
93a37866
A
909 ASSERT(m_expr->isResolveNode());
910 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
911 const Identifier& ident = resolve->identifier();
f9bf01c6 912
81345200 913 if (Local local = generator.local(ident)) {
40a37d08 914 RefPtr<RegisterID> localReg = local.get();
81345200 915 if (local.isReadOnly()) {
93a37866 916 generator.emitReadOnlyExceptionIfNeeded();
40a37d08 917 localReg = generator.emitMove(generator.tempDestination(dst), localReg.get());
81345200
A
918 } else if (local.isCaptured()) {
919 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
40a37d08 920 generator.emitMove(tempDst.get(), localReg.get());
81345200 921 emitIncOrDec(generator, tempDst.get(), m_operator);
40a37d08 922 generator.emitMove(localReg.get(), tempDst.get());
81345200 923 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
93a37866 924 }
40a37d08
A
925 emitIncOrDec(generator, localReg.get(), m_operator);
926 return generator.moveToDestinationIfNeeded(dst, localReg.get());
f9bf01c6
A
927 }
928
81345200
A
929 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
930 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident);
931 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
932 emitIncOrDec(generator, value.get(), m_operator);
933 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
934 return generator.moveToDestinationIfNeeded(dst, value.get());
f9bf01c6
A
935}
936
93a37866 937RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 938{
93a37866
A
939 ASSERT(m_expr->isBracketAccessorNode());
940 BracketAccessorNode* bracketAccessor = static_cast<BracketAccessorNode*>(m_expr);
941 ExpressionNode* baseNode = bracketAccessor->base();
942 ExpressionNode* subscript = bracketAccessor->subscript();
943
944 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(baseNode, bracketAccessor->subscriptHasAssignments(), subscript->isPure(generator));
945 RefPtr<RegisterID> property = generator.emitNode(subscript);
f9bf01c6
A
946 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
947
81345200 948 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
f9bf01c6 949 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
93a37866 950 emitIncOrDec(generator, value, m_operator);
81345200 951 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
f9bf01c6
A
952 generator.emitPutByVal(base.get(), property.get(), value);
953 return generator.moveToDestinationIfNeeded(dst, propDst.get());
954}
955
93a37866 956RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 957{
93a37866
A
958 ASSERT(m_expr->isDotAccessorNode());
959 DotAccessorNode* dotAccessor = static_cast<DotAccessorNode*>(m_expr);
960 ExpressionNode* baseNode = dotAccessor->base();
961 const Identifier& ident = dotAccessor->identifier();
962
963 RefPtr<RegisterID> base = generator.emitNode(baseNode);
f9bf01c6
A
964 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
965
81345200 966 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
93a37866
A
967 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
968 emitIncOrDec(generator, value, m_operator);
81345200 969 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
93a37866 970 generator.emitPutById(base.get(), ident, value);
f9bf01c6
A
971 return generator.moveToDestinationIfNeeded(dst, propDst.get());
972}
973
93a37866 974RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 975{
93a37866
A
976 if (m_expr->isResolveNode())
977 return emitResolve(generator, dst);
978
979 if (m_expr->isBracketAccessorNode())
980 return emitBracket(generator, dst);
981
982 if (m_expr->isDotAccessorNode())
983 return emitDot(generator, dst);
984
14957cd0 985 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
f9bf01c6
A
986 ? "Prefix ++ operator applied to value that is not a reference."
987 : "Prefix -- operator applied to value that is not a reference.");
988}
989
990// ------------------------------ Unary Operation Nodes -----------------------------------
991
992RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
993{
40a37d08 994 RefPtr<RegisterID> src = generator.emitNode(m_expr);
81345200 995 generator.emitExpressionInfo(position(), position(), position());
40a37d08 996 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get());
f9bf01c6
A
997}
998
6fe7ccc8
A
999// ------------------------------ BitwiseNotNode -----------------------------------
1000
1001RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1002{
1003 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
40a37d08
A
1004 RefPtr<RegisterID> src1 = generator.emitNode(m_expr);
1005 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
6fe7ccc8
A
1006}
1007
f9bf01c6
A
1008// ------------------------------ LogicalNotNode -----------------------------------
1009
93a37866 1010void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
f9bf01c6 1011{
f9bf01c6 1012 // reverse the true and false targets
93a37866 1013 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
f9bf01c6
A
1014}
1015
1016
1017// ------------------------------ Binary Operation Nodes -----------------------------------
1018
1019// BinaryOpNode::emitStrcat:
1020//
1021// This node generates an op_strcat operation. This opcode can handle concatenation of three or
1022// more values, where we can determine a set of separate op_add operations would be operating on
1023// string values.
1024//
1025// This function expects to be operating on a graph of AST nodes looking something like this:
1026//
1027// (a)... (b)
1028// \ /
1029// (+) (c)
1030// \ /
1031// [d] ((+))
1032// \ /
1033// [+=]
1034//
1035// The assignment operation is optional, if it exists the register holding the value on the
1036// lefthand side of the assignment should be passing as the optional 'lhs' argument.
1037//
1038// The method should be called on the node at the root of the tree of regular binary add
1039// operations (marked in the diagram with a double set of parentheses). This node must
1040// be performing a string concatenation (determined by statically detecting that at least
1041// one child must be a string).
1042//
1043// Since the minimum number of values being concatenated together is expected to be 3, if
1044// a lhs to a concatenating assignment is not provided then the root add should have at
1045// least one left child that is also an add that can be determined to be operating on strings.
1046//
1047RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
1048{
1049 ASSERT(isAdd());
1050 ASSERT(resultDescriptor().definitelyIsString());
1051
1052 // Create a list of expressions for all the adds in the tree of nodes we can convert into
1053 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
1054 // added first, and the leftmost child is never added, so the vector produced for the
1055 // example above will be [ c, b ].
1056 Vector<ExpressionNode*, 16> reverseExpressionList;
1057 reverseExpressionList.append(m_expr2);
1058
1059 // Examine the left child of the add. So long as this is a string add, add its right-child
1060 // to the list, and keep processing along the left fork.
1061 ExpressionNode* leftMostAddChild = m_expr1;
1062 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
1063 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
1064 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
1065 }
1066
1067 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
1068
1069 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
1070 // We could possibly avoid this (the lhs is converted last anyway, we could let the
1071 // op_strcat node handle its conversion if required).
1072 if (lhs)
1073 temporaryRegisters.append(generator.newTemporary());
1074
1075 // Emit code for the leftmost node ((a) in the example).
1076 temporaryRegisters.append(generator.newTemporary());
1077 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
1078 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
1079
1080 // Note on ordering of conversions:
1081 //
1082 // We maintain the same ordering of conversions as we would see if the concatenations
1083 // was performed as a sequence of adds (otherwise this optimization could change
1084 // behaviour should an object have been provided a valueOf or toString method).
1085 //
1086 // Considering the above example, the sequnce of execution is:
1087 // * evaluate operand (a)
1088 // * evaluate operand (b)
1089 // * convert (a) to primitive <- (this would be triggered by the first add)
1090 // * convert (b) to primitive <- (ditto)
1091 // * evaluate operand (c)
1092 // * convert (c) to primitive <- (this would be triggered by the second add)
1093 // And optionally, if there is an assignment:
1094 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
1095 //
1096 // As such we do not plant an op to convert the leftmost child now. Instead, use
1097 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
1098 // once the second node has been generated. However, if the leftmost child is an
1099 // immediate we can trivially determine that no conversion will be required.
1100 // If this is the case
1101 if (leftMostAddChild->isString())
1102 leftMostAddChildTempRegister = 0;
1103
1104 while (reverseExpressionList.size()) {
1105 ExpressionNode* node = reverseExpressionList.last();
1106 reverseExpressionList.removeLast();
1107
1108 // Emit the code for the current node.
1109 temporaryRegisters.append(generator.newTemporary());
1110 generator.emitNode(temporaryRegisters.last().get(), node);
1111
1112 // On the first iteration of this loop, when we first reach this point we have just
1113 // generated the second node, which means it is time to convert the leftmost operand.
1114 if (leftMostAddChildTempRegister) {
1115 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
1116 leftMostAddChildTempRegister = 0; // Only do this once.
1117 }
1118 // Plant a conversion for this node, if necessary.
1119 if (!node->isString())
1120 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
1121 }
1122 ASSERT(temporaryRegisters.size() >= 3);
1123
1124 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1125 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1126 if (emitExpressionInfoForMe)
81345200 1127 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
f9bf01c6
A
1128 // If there is an assignment convert the lhs now. This will also copy lhs to
1129 // the temporary register we allocated for it.
1130 if (lhs)
1131 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1132
1133 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1134}
1135
93a37866
A
1136void BinaryOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1137{
1138 TriState branchCondition;
1139 ExpressionNode* branchExpression;
1140 tryFoldToBranch(generator, branchCondition, branchExpression);
1141
1142 if (branchCondition == MixedTriState)
1143 ExpressionNode::emitBytecodeInConditionContext(generator, trueTarget, falseTarget, fallThroughMode);
1144 else if (branchCondition == TrueTriState)
1145 generator.emitNodeInConditionContext(branchExpression, trueTarget, falseTarget, fallThroughMode);
1146 else
1147 generator.emitNodeInConditionContext(branchExpression, falseTarget, trueTarget, invert(fallThroughMode));
1148}
1149
1150static inline bool canFoldToBranch(OpcodeID opcodeID, ExpressionNode* branchExpression, JSValue constant)
1151{
1152 ResultType expressionType = branchExpression->resultDescriptor();
1153
1154 if (expressionType.definitelyIsBoolean() && constant.isBoolean())
1155 return true;
1156 else if (expressionType.definitelyIsBoolean() && constant.isInt32() && (constant.asInt32() == 0 || constant.asInt32() == 1))
1157 return opcodeID == op_eq || opcodeID == op_neq; // Strict equality is false in the case of type mismatch.
1158 else if (expressionType.isInt32() && constant.isInt32() && constant.asInt32() == 0)
1159 return true;
1160
1161 return false;
1162}
1163
1164void BinaryOpNode::tryFoldToBranch(BytecodeGenerator& generator, TriState& branchCondition, ExpressionNode*& branchExpression)
1165{
1166 branchCondition = MixedTriState;
1167 branchExpression = 0;
1168
1169 ConstantNode* constant = 0;
1170 if (m_expr1->isConstant()) {
1171 constant = static_cast<ConstantNode*>(m_expr1);
1172 branchExpression = m_expr2;
1173 } else if (m_expr2->isConstant()) {
1174 constant = static_cast<ConstantNode*>(m_expr2);
1175 branchExpression = m_expr1;
1176 }
1177
1178 if (!constant)
1179 return;
1180 ASSERT(branchExpression);
1181
1182 OpcodeID opcodeID = this->opcodeID();
1183 JSValue value = constant->jsValue(generator);
1184 bool canFoldToBranch = JSC::canFoldToBranch(opcodeID, branchExpression, value);
1185 if (!canFoldToBranch)
1186 return;
1187
1188 if (opcodeID == op_eq || opcodeID == op_stricteq)
1189 branchCondition = triState(value.pureToBoolean());
1190 else if (opcodeID == op_neq || opcodeID == op_nstricteq)
1191 branchCondition = triState(!value.pureToBoolean());
1192}
1193
f9bf01c6
A
1194RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1195{
1196 OpcodeID opcodeID = this->opcodeID();
1197
81345200
A
1198 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
1199 generator.emitExpressionInfo(position(), position(), position());
f9bf01c6 1200 return emitStrcat(generator, dst);
81345200 1201 }
f9bf01c6
A
1202
1203 if (opcodeID == op_neq) {
1204 if (m_expr1->isNull() || m_expr2->isNull()) {
1205 RefPtr<RegisterID> src = generator.tempDestination(dst);
1206 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1207 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1208 }
1209 }
1210
93a37866
A
1211 ExpressionNode* left = m_expr1;
1212 ExpressionNode* right = m_expr2;
1213 if (opcodeID == op_neq || opcodeID == op_nstricteq) {
1214 if (left->isString())
1215 std::swap(left, right);
1216 }
1217
1218 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, right->isPure(generator));
1219 bool wasTypeof = generator.m_lastOpcodeID == op_typeof;
40a37d08 1220 RefPtr<RegisterID> src2 = generator.emitNode(right);
81345200 1221 generator.emitExpressionInfo(position(), position(), position());
93a37866
A
1222 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
1223 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1224 if (opcodeID == op_neq)
40a37d08 1225 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
93a37866 1226 else if (opcodeID == op_nstricteq)
40a37d08 1227 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2.get());
93a37866
A
1228 else
1229 RELEASE_ASSERT_NOT_REACHED();
1230 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1231 }
40a37d08 1232 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
81345200
A
1233 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1234 return generator.emitUnaryOp(op_unsigned, result, result);
1235 return result;
f9bf01c6
A
1236}
1237
1238RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1239{
1240 if (m_expr1->isNull() || m_expr2->isNull()) {
1241 RefPtr<RegisterID> src = generator.tempDestination(dst);
1242 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1243 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1244 }
1245
93a37866
A
1246 ExpressionNode* left = m_expr1;
1247 ExpressionNode* right = m_expr2;
1248 if (left->isString())
1249 std::swap(left, right);
1250
1251 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
40a37d08
A
1252 RefPtr<RegisterID> src2 = generator.emitNode(right);
1253 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
f9bf01c6
A
1254}
1255
1256RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1257{
93a37866
A
1258 ExpressionNode* left = m_expr1;
1259 ExpressionNode* right = m_expr2;
1260 if (left->isString())
1261 std::swap(left, right);
1262
1263 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(left, m_rightHasAssignments, m_expr2->isPure(generator));
40a37d08
A
1264 RefPtr<RegisterID> src2 = generator.emitNode(right);
1265 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2.get());
f9bf01c6
A
1266}
1267
f9bf01c6
A
1268RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1269{
1270 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
40a37d08 1271 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
81345200 1272 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
40a37d08 1273 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
f9bf01c6
A
1274}
1275
1276RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1277{
1278 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1279 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
93a37866
A
1280 RefPtr<RegisterID> prototype = generator.newTemporary();
1281 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1282 RefPtr<Label> target = generator.newLabel();
f9bf01c6 1283
81345200 1284 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
93a37866 1285 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
14957cd0 1286
81345200 1287 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
93a37866 1288 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
f9bf01c6 1289
81345200 1290 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
93a37866
A
1291 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
1292 generator.emitLabel(target.get());
1293 return result;
f9bf01c6
A
1294}
1295
1296// ------------------------------ LogicalOpNode ----------------------------
1297
1298RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1299{
1300 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1301 RefPtr<Label> target = generator.newLabel();
1302
1303 generator.emitNode(temp.get(), m_expr1);
1304 if (m_operator == OpLogicalAnd)
1305 generator.emitJumpIfFalse(temp.get(), target.get());
1306 else
1307 generator.emitJumpIfTrue(temp.get(), target.get());
1308 generator.emitNode(temp.get(), m_expr2);
1309 generator.emitLabel(target.get());
1310
1311 return generator.moveToDestinationIfNeeded(dst, temp.get());
1312}
1313
93a37866 1314void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
f9bf01c6 1315{
93a37866
A
1316 RefPtr<Label> afterExpr1 = generator.newLabel();
1317 if (m_operator == OpLogicalAnd)
1318 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, FallThroughMeansTrue);
1319 else
1320 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), FallThroughMeansFalse);
1321 generator.emitLabel(afterExpr1.get());
f9bf01c6 1322
93a37866 1323 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
f9bf01c6
A
1324}
1325
1326// ------------------------------ ConditionalNode ------------------------------
1327
1328RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1329{
1330 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1331 RefPtr<Label> beforeElse = generator.newLabel();
1332 RefPtr<Label> afterElse = generator.newLabel();
1333
93a37866
A
1334 RefPtr<Label> beforeThen = generator.newLabel();
1335 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1336 generator.emitLabel(beforeThen.get());
f9bf01c6
A
1337
1338 generator.emitNode(newDst.get(), m_expr1);
1339 generator.emitJump(afterElse.get());
1340
1341 generator.emitLabel(beforeElse.get());
1342 generator.emitNode(newDst.get(), m_expr2);
1343
1344 generator.emitLabel(afterElse.get());
1345
1346 return newDst.get();
1347}
1348
1349// ------------------------------ ReadModifyResolveNode -----------------------------------
1350
1351// FIXME: should this be moved to be a method on BytecodeGenerator?
1352static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1353{
1354 OpcodeID opcodeID;
1355 switch (oper) {
1356 case OpMultEq:
1357 opcodeID = op_mul;
1358 break;
1359 case OpDivEq:
1360 opcodeID = op_div;
1361 break;
1362 case OpPlusEq:
1363 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1364 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1365 opcodeID = op_add;
1366 break;
1367 case OpMinusEq:
1368 opcodeID = op_sub;
1369 break;
1370 case OpLShift:
1371 opcodeID = op_lshift;
1372 break;
1373 case OpRShift:
1374 opcodeID = op_rshift;
1375 break;
1376 case OpURShift:
1377 opcodeID = op_urshift;
1378 break;
1379 case OpAndEq:
1380 opcodeID = op_bitand;
1381 break;
1382 case OpXOrEq:
1383 opcodeID = op_bitxor;
1384 break;
1385 case OpOrEq:
1386 opcodeID = op_bitor;
1387 break;
1388 case OpModEq:
1389 opcodeID = op_mod;
1390 break;
1391 default:
93a37866 1392 RELEASE_ASSERT_NOT_REACHED();
f9bf01c6
A
1393 return dst;
1394 }
1395
1396 RegisterID* src2 = generator.emitNode(m_right);
1397
1398 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1399 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1400 if (emitExpressionInfoForMe)
81345200
A
1401 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
1402 RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1403 if (oper == OpURShift)
1404 return generator.emitUnaryOp(op_unsigned, result, result);
1405 return result;
f9bf01c6
A
1406}
1407
1408RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1409{
81345200
A
1410 if (Local local = generator.local(m_ident)) {
1411 if (local.isReadOnly()) {
93a37866 1412 generator.emitReadOnlyExceptionIfNeeded();
81345200 1413 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
93a37866
A
1414 }
1415
81345200
A
1416 if (local.isCaptured()
1417 || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
f9bf01c6 1418 RefPtr<RegisterID> result = generator.newTemporary();
81345200 1419 generator.emitMove(result.get(), local.get());
f9bf01c6 1420 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
81345200 1421 generator.emitMove(local.get(), result.get());
f9bf01c6
A
1422 return generator.moveToDestinationIfNeeded(dst, result.get());
1423 }
1424
81345200 1425 RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
f9bf01c6
A
1426 return generator.moveToDestinationIfNeeded(dst, result);
1427 }
1428
81345200
A
1429 JSTextPosition newDivot = divotStart() + m_ident.length();
1430 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
1431 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1432 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound);
1433 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
1434 return generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound);
f9bf01c6
A
1435}
1436
1437// ------------------------------ AssignResolveNode -----------------------------------
1438
1439RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1440{
81345200
A
1441 if (Local local = generator.local(m_ident)) {
1442 if (local.isReadOnly()) {
93a37866 1443 generator.emitReadOnlyExceptionIfNeeded();
f9bf01c6 1444 return generator.emitNode(dst, m_right);
93a37866 1445 }
81345200
A
1446 if (local.isCaptured()) {
1447 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
1448 generator.emitNode(tempDst.get(), m_right);
1449 generator.emitMove(local.get(), tempDst.get());
1450 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
1451 }
1452 RegisterID* result = generator.emitNode(local.get(), m_right);
f9bf01c6
A
1453 return generator.moveToDestinationIfNeeded(dst, result);
1454 }
1455
81345200
A
1456 if (generator.isStrictMode())
1457 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1458 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
f9bf01c6
A
1459 if (dst == generator.ignoredResult())
1460 dst = 0;
81345200
A
1461 RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
1462 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1463 return generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
f9bf01c6
A
1464}
1465
1466// ------------------------------ AssignDotNode -----------------------------------
1467
1468RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1469{
1470 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1471 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
40a37d08 1472 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
81345200 1473 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
40a37d08 1474 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
6fe7ccc8
A
1475 generator.emitPutById(base.get(), m_ident, forwardResult);
1476 return generator.moveToDestinationIfNeeded(dst, forwardResult);
f9bf01c6
A
1477}
1478
1479// ------------------------------ ReadModifyDotNode -----------------------------------
1480
1481RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1482{
1483 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1484
81345200 1485 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
f9bf01c6 1486 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
81345200 1487 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, static_cast<JSC::Operator>(m_operator), OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
f9bf01c6 1488
81345200 1489 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
f9bf01c6
A
1490 return generator.emitPutById(base.get(), m_ident, updatedValue);
1491}
1492
1493// ------------------------------ AssignErrorNode -----------------------------------
1494
1495RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1496{
14957cd0 1497 return emitThrowReferenceError(generator, "Left side of assignment is not a reference.");
f9bf01c6
A
1498}
1499
1500// ------------------------------ AssignBracketNode -----------------------------------
1501
1502RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1503{
1504 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1505 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1506 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
40a37d08 1507 RefPtr<RegisterID> result = generator.emitNode(value.get(), m_right);
f9bf01c6 1508
81345200 1509 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
40a37d08 1510 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
6fe7ccc8
A
1511 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1512 return generator.moveToDestinationIfNeeded(dst, forwardResult);
f9bf01c6
A
1513}
1514
1515// ------------------------------ ReadModifyBracketNode -----------------------------------
1516
1517RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1518{
1519 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1520 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1521
81345200 1522 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
f9bf01c6 1523 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
81345200 1524 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, static_cast<JSC::Operator>(m_operator), OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
f9bf01c6 1525
81345200 1526 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
f9bf01c6
A
1527 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1528
1529 return updatedValue;
1530}
1531
1532// ------------------------------ CommaNode ------------------------------------
1533
1534RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1535{
1536 ASSERT(m_expressions.size() > 1);
1537 for (size_t i = 0; i < m_expressions.size() - 1; i++)
1538 generator.emitNode(generator.ignoredResult(), m_expressions[i]);
1539 return generator.emitNode(dst, m_expressions.last());
1540}
1541
1542// ------------------------------ ConstDeclNode ------------------------------------
1543
1544RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1545{
6fe7ccc8 1546 // FIXME: This code does not match the behavior of const in Firefox.
81345200 1547 if (Local local = generator.constLocal(m_ident)) {
f9bf01c6 1548 if (!m_init)
81345200 1549 return local.get();
f9bf01c6 1550
81345200
A
1551 if (local.isCaptured()) {
1552 RefPtr<RegisterID> tempDst = generator.newTemporary();
1553 generator.emitNode(tempDst.get(), m_init);
1554 return generator.emitMove(local.get(), tempDst.get());
1555 }
1556
1557 return generator.emitNode(local.get(), m_init);
f9bf01c6
A
1558 }
1559
6fe7ccc8
A
1560 RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1561
93a37866
A
1562 if (generator.codeType() == GlobalCode)
1563 return generator.emitInitGlobalConst(m_ident, value.get());
6fe7ccc8
A
1564
1565 if (generator.codeType() != EvalCode)
1566 return value.get();
1567
93a37866 1568 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
81345200
A
1569 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1570 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound);
f9bf01c6
A
1571}
1572
1573RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1574{
1575 RegisterID* result = 0;
1576 for (ConstDeclNode* n = this; n; n = n->m_next)
1577 result = n->emitCodeSingle(generator);
1578
1579 return result;
1580}
1581
1582// ------------------------------ ConstStatementNode -----------------------------
1583
93a37866 1584void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6 1585{
81345200 1586 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
93a37866 1587 generator.emitNode(m_next);
f9bf01c6
A
1588}
1589
1590// ------------------------------ SourceElements -------------------------------
1591
1592
1593inline StatementNode* SourceElements::lastStatement() const
1594{
1595 size_t size = m_statements.size();
1596 return size ? m_statements[size - 1] : 0;
1597}
1598
1599inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1600{
1601 size_t size = m_statements.size();
1602 for (size_t i = 0; i < size; ++i)
1603 generator.emitNode(dst, m_statements[i]);
1604}
1605
1606// ------------------------------ BlockNode ------------------------------------
1607
1608inline StatementNode* BlockNode::lastStatement() const
1609{
1610 return m_statements ? m_statements->lastStatement() : 0;
1611}
1612
14957cd0
A
1613inline StatementNode* BlockNode::singleStatement() const
1614{
1615 return m_statements ? m_statements->singleStatement() : 0;
1616}
1617
93a37866 1618void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 1619{
93a37866
A
1620 if (!m_statements)
1621 return;
1622 m_statements->emitBytecode(generator, dst);
f9bf01c6
A
1623}
1624
1625// ------------------------------ EmptyStatementNode ---------------------------
1626
93a37866 1627void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6 1628{
81345200 1629 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6
A
1630}
1631
1632// ------------------------------ DebuggerStatementNode ---------------------------
1633
93a37866 1634void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6 1635{
81345200 1636 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
f9bf01c6
A
1637}
1638
1639// ------------------------------ ExprStatementNode ----------------------------
1640
93a37866 1641void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6
A
1642{
1643 ASSERT(m_expr);
81345200 1644 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
93a37866 1645 generator.emitNode(dst, m_expr);
f9bf01c6
A
1646}
1647
1648// ------------------------------ VarStatementNode ----------------------------
1649
93a37866 1650void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6
A
1651{
1652 ASSERT(m_expr);
81345200 1653 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
93a37866 1654 generator.emitNode(m_expr);
f9bf01c6
A
1655}
1656
93a37866 1657// ------------------------------ IfElseNode ---------------------------------------
f9bf01c6 1658
93a37866 1659static inline StatementNode* singleStatement(StatementNode* statementNode)
f9bf01c6 1660{
93a37866
A
1661 if (statementNode->isBlock())
1662 return static_cast<BlockNode*>(statementNode)->singleStatement();
1663 return statementNode;
1664}
f9bf01c6 1665
93a37866
A
1666bool IfElseNode::tryFoldBreakAndContinue(BytecodeGenerator& generator, StatementNode* ifBlock,
1667 Label*& trueTarget, FallThroughMode& fallThroughMode)
1668{
1669 StatementNode* singleStatement = JSC::singleStatement(ifBlock);
1670 if (!singleStatement)
1671 return false;
1672
1673 if (singleStatement->isBreak()) {
1674 BreakNode* breakNode = static_cast<BreakNode*>(singleStatement);
1675 Label* target = breakNode->trivialTarget(generator);
1676 if (!target)
1677 return false;
1678 trueTarget = target;
1679 fallThroughMode = FallThroughMeansFalse;
1680 return true;
f9bf01c6
A
1681 }
1682
93a37866
A
1683 if (singleStatement->isContinue()) {
1684 ContinueNode* continueNode = static_cast<ContinueNode*>(singleStatement);
1685 Label* target = continueNode->trivialTarget(generator);
1686 if (!target)
1687 return false;
1688 trueTarget = target;
1689 fallThroughMode = FallThroughMeansFalse;
1690 return true;
1691 }
f9bf01c6 1692
93a37866 1693 return false;
f9bf01c6
A
1694}
1695
93a37866 1696void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 1697{
81345200 1698 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6 1699
93a37866 1700 RefPtr<Label> beforeThen = generator.newLabel();
f9bf01c6
A
1701 RefPtr<Label> beforeElse = generator.newLabel();
1702 RefPtr<Label> afterElse = generator.newLabel();
1703
93a37866
A
1704 Label* trueTarget = beforeThen.get();
1705 Label* falseTarget = beforeElse.get();
1706 FallThroughMode fallThroughMode = FallThroughMeansTrue;
1707 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
f9bf01c6 1708
93a37866
A
1709 generator.emitNodeInConditionContext(m_condition, trueTarget, falseTarget, fallThroughMode);
1710 generator.emitLabel(beforeThen.get());
1711
1712 if (!didFoldIfBlock) {
1713 generator.emitNode(dst, m_ifBlock);
1714 if (m_elseBlock)
1715 generator.emitJump(afterElse.get());
1716 }
f9bf01c6
A
1717
1718 generator.emitLabel(beforeElse.get());
1719
93a37866
A
1720 if (m_elseBlock)
1721 generator.emitNode(dst, m_elseBlock);
f9bf01c6
A
1722
1723 generator.emitLabel(afterElse.get());
f9bf01c6
A
1724}
1725
1726// ------------------------------ DoWhileNode ----------------------------------
1727
93a37866 1728void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 1729{
93a37866 1730 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
f9bf01c6
A
1731
1732 RefPtr<Label> topOfLoop = generator.newLabel();
1733 generator.emitLabel(topOfLoop.get());
6fe7ccc8 1734 generator.emitLoopHint();
81345200 1735 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
93a37866
A
1736
1737 generator.emitNode(dst, m_statement);
f9bf01c6
A
1738
1739 generator.emitLabel(scope->continueTarget());
81345200 1740 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
93a37866 1741 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
f9bf01c6
A
1742
1743 generator.emitLabel(scope->breakTarget());
f9bf01c6
A
1744}
1745
1746// ------------------------------ WhileNode ------------------------------------
1747
93a37866 1748void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 1749{
93a37866
A
1750 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1751 RefPtr<Label> topOfLoop = generator.newLabel();
f9bf01c6 1752
81345200 1753 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->startOffset(), m_expr->lineStartOffset());
93a37866 1754 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
f9bf01c6 1755
f9bf01c6 1756 generator.emitLabel(topOfLoop.get());
6fe7ccc8 1757 generator.emitLoopHint();
f9bf01c6
A
1758
1759 generator.emitNode(dst, m_statement);
1760
1761 generator.emitLabel(scope->continueTarget());
81345200 1762 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6 1763
93a37866 1764 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
f9bf01c6
A
1765
1766 generator.emitLabel(scope->breakTarget());
f9bf01c6
A
1767}
1768
1769// ------------------------------ ForNode --------------------------------------
1770
93a37866 1771void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 1772{
93a37866 1773 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
f9bf01c6 1774
81345200 1775 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6
A
1776
1777 if (m_expr1)
1778 generator.emitNode(generator.ignoredResult(), m_expr1);
93a37866 1779
f9bf01c6 1780 RefPtr<Label> topOfLoop = generator.newLabel();
93a37866
A
1781 if (m_expr2)
1782 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
1783
f9bf01c6 1784 generator.emitLabel(topOfLoop.get());
6fe7ccc8 1785 generator.emitLoopHint();
f9bf01c6 1786
93a37866 1787 generator.emitNode(dst, m_statement);
f9bf01c6
A
1788
1789 generator.emitLabel(scope->continueTarget());
81345200 1790 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6
A
1791 if (m_expr3)
1792 generator.emitNode(generator.ignoredResult(), m_expr3);
1793
93a37866
A
1794 if (m_expr2)
1795 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1796 else
f9bf01c6
A
1797 generator.emitJump(topOfLoop.get());
1798
1799 generator.emitLabel(scope->breakTarget());
f9bf01c6
A
1800}
1801
1802// ------------------------------ ForInNode ------------------------------------
1803
93a37866 1804void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 1805{
93a37866 1806 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
f9bf01c6 1807
81345200 1808 if (!m_lexpr->isAssignmentLocation()) {
93a37866
A
1809 emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
1810 return;
1811 }
f9bf01c6 1812
81345200 1813 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6
A
1814
1815 RefPtr<RegisterID> base = generator.newTemporary();
1816 generator.emitNode(base.get(), m_expr);
1817 RefPtr<RegisterID> i = generator.newTemporary();
1818 RefPtr<RegisterID> size = generator.newTemporary();
1819 RefPtr<RegisterID> expectedSubscript;
1820 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
1821 generator.emitJump(scope->continueTarget());
1822
1823 RefPtr<Label> loopStart = generator.newLabel();
1824 generator.emitLabel(loopStart.get());
6fe7ccc8 1825 generator.emitLoopHint();
f9bf01c6
A
1826
1827 RegisterID* propertyName;
1828 bool optimizedForinAccess = false;
1829 if (m_lexpr->isResolveNode()) {
1830 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
81345200
A
1831 Local local = generator.local(ident);
1832 if (!local.get()) {
f9bf01c6
A
1833 propertyName = generator.newTemporary();
1834 RefPtr<RegisterID> protect = propertyName;
81345200
A
1835 if (generator.isStrictMode())
1836 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1837 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
1838 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1839 generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
f9bf01c6 1840 } else {
81345200
A
1841 expectedSubscript = generator.newTemporary();
1842 propertyName = expectedSubscript.get();
1843 generator.emitMove(local.get(), propertyName);
1844 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), local.get());
f9bf01c6
A
1845 optimizedForinAccess = true;
1846 }
1847 } else if (m_lexpr->isDotAccessorNode()) {
1848 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1849 const Identifier& ident = assignNode->identifier();
1850 propertyName = generator.newTemporary();
1851 RefPtr<RegisterID> protect = propertyName;
1852 RegisterID* base = generator.emitNode(assignNode->base());
1853
81345200 1854 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
f9bf01c6 1855 generator.emitPutById(base, ident, propertyName);
81345200 1856 } else if (m_lexpr->isBracketAccessorNode()) {
f9bf01c6
A
1857 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1858 propertyName = generator.newTemporary();
1859 RefPtr<RegisterID> protect = propertyName;
1860 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1861 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1862
81345200 1863 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
f9bf01c6 1864 generator.emitPutByVal(base.get(), subscript, propertyName);
81345200
A
1865 } else {
1866 ASSERT(m_lexpr->isDeconstructionNode());
1867 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
1868 auto binding = assignNode->bindings();
1869 if (binding->isBindingNode()) {
1870 auto simpleBinding = static_cast<BindingNode*>(binding);
1871 Identifier ident = simpleBinding->boundProperty();
1872 Local local = generator.local(ident);
1873 propertyName = local.get();
1874 if (!propertyName || local.isCaptured())
1875 goto genericBinding;
1876 expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
1877 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
1878 optimizedForinAccess = true;
1879 goto completedSimpleBinding;
1880 } else {
1881 genericBinding:
1882 propertyName = generator.newTemporary();
1883 RefPtr<RegisterID> protect(propertyName);
1884 assignNode->bindings()->bindValue(generator, propertyName);
1885 }
1886 completedSimpleBinding:
1887 ;
1888 }
f9bf01c6
A
1889
1890 generator.emitNode(dst, m_statement);
1891
1892 if (optimizedForinAccess)
1893 generator.popOptimisedForIn();
1894
1895 generator.emitLabel(scope->continueTarget());
1896 generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
81345200 1897 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6 1898 generator.emitLabel(scope->breakTarget());
f9bf01c6
A
1899}
1900
81345200
A
1901// ------------------------------ ForOfNode ------------------------------------
1902void ForOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1903{
1904 if (!m_lexpr->isAssignmentLocation()) {
1905 emitThrowReferenceError(generator, "Left side of for-of statement is not a reference.");
1906 return;
1907 }
1908
1909 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1910
1911 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1912 auto extractor = [this, dst](BytecodeGenerator& generator, RegisterID* value)
1913 {
1914 if (m_lexpr->isResolveNode()) {
1915 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1916 if (Local local = generator.local(ident))
1917 generator.emitMove(local.get(), value);
1918 else {
1919 if (generator.isStrictMode())
1920 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1921 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
1922 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1923 generator.emitPutToScope(scope, ident, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
1924 }
1925 } else if (m_lexpr->isDotAccessorNode()) {
1926 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1927 const Identifier& ident = assignNode->identifier();
1928 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1929
1930 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1931 generator.emitPutById(base.get(), ident, value);
1932 } else if (m_lexpr->isBracketAccessorNode()) {
1933 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1934 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1935 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1936
1937 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1938 generator.emitPutByVal(base.get(), subscript, value);
1939 } else {
1940 ASSERT(m_lexpr->isDeconstructionNode());
1941 DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
1942 assignNode->bindings()->bindValue(generator, value);
1943 }
1944 generator.emitNode(dst, m_statement);
1945 };
1946 generator.emitEnumeration(this, m_expr, extractor);
1947}
1948
f9bf01c6
A
1949// ------------------------------ ContinueNode ---------------------------------
1950
93a37866
A
1951Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
1952{
1953 if (generator.shouldEmitDebugHooks())
1954 return 0;
1955
81345200 1956 LabelScopePtr scope = generator.continueTarget(m_ident);
93a37866
A
1957 ASSERT(scope);
1958
1959 if (generator.scopeDepth() != scope->scopeDepth())
1960 return 0;
1961
1962 return scope->continueTarget();
1963}
1964
1965void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6 1966{
81345200 1967 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6 1968
81345200 1969 LabelScopePtr scope = generator.continueTarget(m_ident);
14957cd0 1970 ASSERT(scope);
f9bf01c6 1971
93a37866
A
1972 generator.emitPopScopes(scope->scopeDepth());
1973 generator.emitJump(scope->continueTarget());
f9bf01c6
A
1974}
1975
1976// ------------------------------ BreakNode ------------------------------------
1977
93a37866 1978Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
f9bf01c6 1979{
93a37866
A
1980 if (generator.shouldEmitDebugHooks())
1981 return 0;
1982
81345200 1983 LabelScopePtr scope = generator.breakTarget(m_ident);
93a37866
A
1984 ASSERT(scope);
1985
1986 if (generator.scopeDepth() != scope->scopeDepth())
1987 return 0;
1988
1989 return scope->breakTarget();
1990}
1991
1992void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1993{
81345200 1994 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6 1995
81345200 1996 LabelScopePtr scope = generator.breakTarget(m_ident);
14957cd0 1997 ASSERT(scope);
f9bf01c6 1998
93a37866
A
1999 generator.emitPopScopes(scope->scopeDepth());
2000 generator.emitJump(scope->breakTarget());
f9bf01c6
A
2001}
2002
2003// ------------------------------ ReturnNode -----------------------------------
2004
93a37866 2005void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 2006{
81345200 2007 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
14957cd0 2008 ASSERT(generator.codeType() == FunctionCode);
f9bf01c6
A
2009
2010 if (dst == generator.ignoredResult())
2011 dst = 0;
93a37866
A
2012
2013 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
f9bf01c6 2014 if (generator.scopeDepth()) {
93a37866
A
2015 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
2016 generator.emitPopScopes(0);
f9bf01c6 2017 }
93a37866 2018
81345200 2019 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
93a37866 2020 generator.emitReturn(returnRegister.get());
f9bf01c6
A
2021}
2022
2023// ------------------------------ WithNode -------------------------------------
2024
93a37866 2025void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 2026{
81345200 2027 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
93a37866
A
2028
2029 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
81345200 2030 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
93a37866
A
2031 generator.emitPushWithScope(scope.get());
2032 generator.emitNode(dst, m_statement);
f9bf01c6 2033 generator.emitPopScope();
f9bf01c6
A
2034}
2035
2036// ------------------------------ CaseClauseNode --------------------------------
2037
2038inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2039{
93a37866
A
2040 if (!m_statements)
2041 return;
2042 m_statements->emitBytecode(generator, dst);
f9bf01c6
A
2043}
2044
2045// ------------------------------ CaseBlockNode --------------------------------
2046
2047enum SwitchKind {
2048 SwitchUnset = 0,
2049 SwitchNumber = 1,
2050 SwitchString = 2,
2051 SwitchNeither = 3
2052};
2053
2054static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
2055{
2056 for (; list; list = list->getNext()) {
2057 ExpressionNode* clauseExpression = list->getClause()->expr();
2058 literalVector.append(clauseExpression);
2059 if (clauseExpression->isNumber()) {
2060 double value = static_cast<NumberNode*>(clauseExpression)->value();
2061 int32_t intVal = static_cast<int32_t>(value);
2062 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
2063 typeForTable = SwitchNeither;
2064 break;
2065 }
2066 if (intVal < min_num)
2067 min_num = intVal;
2068 if (intVal > max_num)
2069 max_num = intVal;
2070 typeForTable = SwitchNumber;
2071 continue;
2072 }
2073 if (clauseExpression->isString()) {
2074 if (typeForTable & ~SwitchString) {
2075 typeForTable = SwitchNeither;
2076 break;
2077 }
93a37866 2078 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
14957cd0 2079 if (singleCharacterSwitch &= value.length() == 1) {
6fe7ccc8 2080 int32_t intVal = value[0];
f9bf01c6
A
2081 if (intVal < min_num)
2082 min_num = intVal;
2083 if (intVal > max_num)
2084 max_num = intVal;
2085 }
2086 typeForTable = SwitchString;
2087 continue;
2088 }
2089 typeForTable = SwitchNeither;
2090 break;
2091 }
2092}
93a37866
A
2093
2094static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
f9bf01c6 2095{
93a37866
A
2096 size_t length = 0;
2097 for (ClauseListNode* node = list1; node; node = node->getNext())
2098 ++length;
2099 for (ClauseListNode* node = list2; node; node = node->getNext())
2100 ++length;
2101 return length;
2102}
2103
2104SwitchInfo::SwitchType CaseBlockNode::tryTableSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
2105{
2106 if (length(m_list1, m_list2) < s_tableSwitchMinimum)
2107 return SwitchInfo::SwitchNone;
2108
f9bf01c6
A
2109 SwitchKind typeForTable = SwitchUnset;
2110 bool singleCharacterSwitch = true;
2111
2112 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2113 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
2114
2115 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
2116 return SwitchInfo::SwitchNone;
2117
2118 if (typeForTable == SwitchNumber) {
2119 int32_t range = max_num - min_num;
2120 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2121 return SwitchInfo::SwitchImmediate;
2122 return SwitchInfo::SwitchNone;
2123 }
2124
2125 ASSERT(typeForTable == SwitchString);
2126
2127 if (singleCharacterSwitch) {
2128 int32_t range = max_num - min_num;
2129 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
2130 return SwitchInfo::SwitchCharacter;
2131 }
2132
2133 return SwitchInfo::SwitchString;
2134}
2135
93a37866 2136void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
f9bf01c6
A
2137{
2138 RefPtr<Label> defaultLabel;
2139 Vector<RefPtr<Label>, 8> labelVector;
2140 Vector<ExpressionNode*, 8> literalVector;
2141 int32_t min_num = std::numeric_limits<int32_t>::max();
2142 int32_t max_num = std::numeric_limits<int32_t>::min();
93a37866 2143 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
f9bf01c6
A
2144
2145 if (switchType != SwitchInfo::SwitchNone) {
2146 // Prepare the various labels
2147 for (uint32_t i = 0; i < literalVector.size(); i++)
2148 labelVector.append(generator.newLabel());
2149 defaultLabel = generator.newLabel();
2150 generator.beginSwitch(switchExpression, switchType);
2151 } else {
2152 // Setup jumps
2153 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2154 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2155 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2156 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2157 labelVector.append(generator.newLabel());
2158 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2159 }
2160
2161 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2162 RefPtr<RegisterID> clauseVal = generator.newTemporary();
2163 generator.emitNode(clauseVal.get(), list->getClause()->expr());
2164 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
2165 labelVector.append(generator.newLabel());
2166 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
2167 }
2168 defaultLabel = generator.newLabel();
2169 generator.emitJump(defaultLabel.get());
2170 }
2171
f9bf01c6
A
2172 size_t i = 0;
2173 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
2174 generator.emitLabel(labelVector[i++].get());
2175 list->getClause()->emitBytecode(generator, dst);
2176 }
2177
2178 if (m_defaultClause) {
2179 generator.emitLabel(defaultLabel.get());
2180 m_defaultClause->emitBytecode(generator, dst);
2181 }
2182
2183 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
2184 generator.emitLabel(labelVector[i++].get());
2185 list->getClause()->emitBytecode(generator, dst);
2186 }
2187 if (!m_defaultClause)
2188 generator.emitLabel(defaultLabel.get());
2189
2190 ASSERT(i == labelVector.size());
2191 if (switchType != SwitchInfo::SwitchNone) {
2192 ASSERT(labelVector.size() == literalVector.size());
2193 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
2194 }
f9bf01c6
A
2195}
2196
2197// ------------------------------ SwitchNode -----------------------------------
2198
93a37866 2199void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 2200{
81345200 2201 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6 2202
93a37866 2203 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
f9bf01c6
A
2204
2205 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
93a37866 2206 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
f9bf01c6
A
2207
2208 generator.emitLabel(scope->breakTarget());
f9bf01c6
A
2209}
2210
2211// ------------------------------ LabelNode ------------------------------------
2212
93a37866 2213void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 2214{
81345200 2215 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6 2216
14957cd0 2217 ASSERT(!generator.breakTarget(m_name));
f9bf01c6 2218
93a37866
A
2219 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
2220 generator.emitNode(dst, m_statement);
f9bf01c6
A
2221
2222 generator.emitLabel(scope->breakTarget());
f9bf01c6
A
2223}
2224
2225// ------------------------------ ThrowNode ------------------------------------
2226
93a37866 2227void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6 2228{
81345200 2229 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
f9bf01c6
A
2230
2231 if (dst == generator.ignoredResult())
2232 dst = 0;
2233 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
81345200 2234 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
f9bf01c6 2235 generator.emitThrow(expr.get());
f9bf01c6
A
2236}
2237
2238// ------------------------------ TryNode --------------------------------------
2239
93a37866 2240void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
f9bf01c6
A
2241{
2242 // NOTE: The catch and finally blocks must be labeled explicitly, so the
2243 // optimizer knows they may be jumped to from anywhere.
2244
81345200 2245 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
93a37866
A
2246
2247 ASSERT(m_catchBlock || m_finallyBlock);
f9bf01c6
A
2248
2249 RefPtr<Label> tryStartLabel = generator.newLabel();
93a37866
A
2250 generator.emitLabel(tryStartLabel.get());
2251
6fe7ccc8
A
2252 if (m_finallyBlock)
2253 generator.pushFinallyContext(m_finallyBlock);
93a37866 2254 TryData* tryData = generator.pushTry(tryStartLabel.get());
f9bf01c6 2255
f9bf01c6
A
2256 generator.emitNode(dst, m_tryBlock);
2257
2258 if (m_catchBlock) {
2259 RefPtr<Label> catchEndLabel = generator.newLabel();
2260
2261 // Normal path: jump over the catch block.
2262 generator.emitJump(catchEndLabel.get());
2263
2264 // Uncaught exception path: the catch block.
2265 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
93a37866
A
2266 RefPtr<RegisterID> exceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), here.get());
2267
2268 if (m_finallyBlock) {
2269 // If the catch block throws an exception and we have a finally block, then the finally
2270 // block should "catch" that exception.
2271 tryData = generator.pushTry(here.get());
2272 }
2273
81345200 2274 generator.emitPushCatchScope(m_exceptionIdent, exceptionRegister.get(), DontDelete);
f9bf01c6
A
2275 generator.emitNode(dst, m_catchBlock);
2276 generator.emitPopScope();
2277 generator.emitLabel(catchEndLabel.get());
2278 }
2279
2280 if (m_finallyBlock) {
93a37866
A
2281 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2282
f9bf01c6 2283 generator.popFinallyContext();
6fe7ccc8 2284
f9bf01c6
A
2285 RefPtr<Label> finallyEndLabel = generator.newLabel();
2286
6fe7ccc8
A
2287 // Normal path: run the finally code, and jump to the end.
2288 generator.emitNode(dst, m_finallyBlock);
f9bf01c6
A
2289 generator.emitJump(finallyEndLabel.get());
2290
2291 // Uncaught exception path: invoke the finally block, then re-throw the exception.
93a37866 2292 RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
f9bf01c6 2293 generator.emitNode(dst, m_finallyBlock);
6fe7ccc8 2294 generator.emitThrow(tempExceptionRegister.get());
f9bf01c6
A
2295
2296 generator.emitLabel(finallyEndLabel.get());
2297 }
f9bf01c6
A
2298}
2299
2300// ------------------------------ ScopeNode -----------------------------
2301
2302inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2303{
93a37866
A
2304 if (!m_statements)
2305 return;
2306 m_statements->emitBytecode(generator, dst);
f9bf01c6
A
2307}
2308
2309// ------------------------------ ProgramNode -----------------------------
2310
93a37866 2311void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6 2312{
81345200 2313 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
f9bf01c6
A
2314
2315 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2316 generator.emitLoad(dstRegister.get(), jsUndefined());
2317 emitStatementsBytecode(generator, dstRegister.get());
2318
81345200 2319 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
f9bf01c6 2320 generator.emitEnd(dstRegister.get());
f9bf01c6
A
2321}
2322
2323// ------------------------------ EvalNode -----------------------------
2324
93a37866 2325void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6 2326{
81345200 2327 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
f9bf01c6
A
2328
2329 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2330 generator.emitLoad(dstRegister.get(), jsUndefined());
2331 emitStatementsBytecode(generator, dstRegister.get());
2332
81345200 2333 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
f9bf01c6 2334 generator.emitEnd(dstRegister.get());
f9bf01c6
A
2335}
2336
2337// ------------------------------ FunctionBodyNode -----------------------------
2338
93a37866 2339void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
f9bf01c6 2340{
81345200 2341 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
f9bf01c6 2342 emitStatementsBytecode(generator, generator.ignoredResult());
14957cd0 2343
f9bf01c6 2344 StatementNode* singleStatement = this->singleStatement();
14957cd0
A
2345 ReturnNode* returnNode = 0;
2346
2347 // Check for a return statement at the end of a function composed of a single block.
f9bf01c6
A
2348 if (singleStatement && singleStatement->isBlock()) {
2349 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2350 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
14957cd0
A
2351 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
2352 }
2353
2354 // If there is no return we must automatically insert one.
2355 if (!returnNode) {
2356 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
81345200
A
2357 ASSERT(startOffset() >= lineStartOffset());
2358 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
14957cd0 2359 generator.emitReturn(r0);
93a37866 2360 return;
14957cd0
A
2361 }
2362
2363 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
2364 if (static_cast<BlockNode*>(singleStatement)->singleStatement()) {
2365 ExpressionNode* returnValueExpression = returnNode->value();
2366 if (returnValueExpression && returnValueExpression->isSubtract()) {
2367 ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
2368 ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
6fe7ccc8
A
2369 if (lhsExpression->isResolveNode()
2370 && rhsExpression->isResolveNode()
2371 && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
2372 && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
2373
2374 generator.setIsNumericCompareFunction(true);
14957cd0
A
2375 }
2376 }
f9bf01c6 2377 }
f9bf01c6
A
2378}
2379
2380// ------------------------------ FuncDeclNode ---------------------------------
2381
93a37866 2382void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
f9bf01c6 2383{
f9bf01c6
A
2384}
2385
2386// ------------------------------ FuncExprNode ---------------------------------
2387
2388RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2389{
2390 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2391}
81345200
A
2392
2393// ------------------------------ DeconstructingAssignmentNode -----------------
2394RegisterID* DeconstructingAssignmentNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2395{
2396 if (RegisterID* result = m_bindings->emitDirectBinding(generator, dst, m_initializer))
2397 return result;
2398 RefPtr<RegisterID> initializer = generator.tempDestination(dst);
2399 generator.emitNode(initializer.get(), m_initializer);
2400 m_bindings->bindValue(generator, initializer.get());
2401 return generator.moveToDestinationIfNeeded(dst, initializer.get());
2402}
2403
2404DeconstructionPatternNode::~DeconstructionPatternNode()
2405{
2406}
2407
2408void ArrayPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
2409{
2410 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2411 auto target = m_targetPatterns[i];
2412 if (!target)
2413 continue;
2414 RefPtr<RegisterID> temp = generator.newTemporary();
2415 generator.emitLoad(temp.get(), jsNumber(i));
2416 generator.emitGetByVal(temp.get(), rhs, temp.get());
2417 target->bindValue(generator, temp.get());
2418 }
2419}
2420
2421RegisterID* ArrayPatternNode::emitDirectBinding(BytecodeGenerator& generator, RegisterID* dst, ExpressionNode* rhs)
2422{
2423 if (rhs->isResolveNode()
2424 && generator.willResolveToArguments(static_cast<ResolveNode*>(rhs)->identifier())
2425 && !generator.symbolTable().slowArguments()) {
2426 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2427 auto target = m_targetPatterns[i];
2428 if (!target)
2429 continue;
2430
2431 RefPtr<RegisterID> temp = generator.newTemporary();
2432 generator.emitLoad(temp.get(), jsNumber(i));
2433 generator.emitGetArgumentByVal(temp.get(), generator.uncheckedRegisterForArguments(), temp.get());
2434 target->bindValue(generator, temp.get());
2435 }
2436 if (dst == generator.ignoredResult() || !dst)
2437 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
2438 Local local = generator.local(generator.vm()->propertyNames->arguments);
2439 return generator.moveToDestinationIfNeeded(dst, local.get());
2440 }
2441 if (!rhs->isSimpleArray())
2442 return 0;
2443
2444 RefPtr<RegisterID> resultRegister;
2445 if (dst && dst != generator.ignoredResult())
2446 resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
2447 ElementNode* elementNodes = static_cast<ArrayNode*>(rhs)->elements();
2448 Vector<ExpressionNode*> elements;
2449 for (; elementNodes; elementNodes = elementNodes->next())
2450 elements.append(elementNodes->value());
2451 if (m_targetPatterns.size() != elements.size())
2452 return 0;
2453 Vector<RefPtr<RegisterID>> registers;
2454 registers.reserveCapacity(m_targetPatterns.size());
2455 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2456 registers.uncheckedAppend(generator.newTemporary());
2457 generator.emitNode(registers.last().get(), elements[i]);
2458 if (resultRegister)
2459 generator.emitPutByIndex(resultRegister.get(), i, registers.last().get());
2460 }
2461
2462 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2463 if (m_targetPatterns[i])
2464 m_targetPatterns[i]->bindValue(generator, registers[i].get());
2465 }
2466 if (resultRegister)
2467 return generator.moveToDestinationIfNeeded(dst, resultRegister.get());
2468 return generator.emitLoad(generator.finalDestination(dst), jsUndefined());
2469}
2470
2471void ArrayPatternNode::toString(StringBuilder& builder) const
2472{
2473 builder.append('[');
2474 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2475 if (!m_targetPatterns[i]) {
2476 builder.append(',');
2477 continue;
2478 }
2479 m_targetPatterns[i]->toString(builder);
2480 if (i < m_targetPatterns.size() - 1)
2481 builder.append(',');
2482 }
2483 builder.append(']');
2484}
2485
2486void ArrayPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2487{
2488 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2489 if (DeconstructionPatternNode* node = m_targetPatterns[i].get())
2490 node->collectBoundIdentifiers(identifiers);
2491 }
2492}
2493
2494void ObjectPatternNode::toString(StringBuilder& builder) const
2495{
2496 builder.append('{');
2497 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2498 if (m_targetPatterns[i].wasString) {
2499 builder.append('"');
2500 escapeStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
2501 builder.append('"');
2502 } else
2503 builder.append(m_targetPatterns[i].propertyName.string());
2504 builder.append(":");
2505 m_targetPatterns[i].pattern->toString(builder);
2506 if (i < m_targetPatterns.size() - 1)
2507 builder.append(',');
2508 }
2509 builder.append('}');
2510}
2511
2512void ObjectPatternNode::bindValue(BytecodeGenerator& generator, RegisterID* rhs) const
2513{
2514 for (size_t i = 0; i < m_targetPatterns.size(); i++) {
2515 auto& target = m_targetPatterns[i];
2516 RefPtr<RegisterID> temp = generator.newTemporary();
2517 generator.emitGetById(temp.get(), rhs, target.propertyName);
2518 target.pattern->bindValue(generator, temp.get());
2519 }
2520}
2521
2522void ObjectPatternNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2523{
2524 for (size_t i = 0; i < m_targetPatterns.size(); i++)
2525 m_targetPatterns[i].pattern->collectBoundIdentifiers(identifiers);
2526}
2527
2528void BindingNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
2529{
2530 if (Local local = generator.local(m_boundProperty)) {
2531 if (local.isReadOnly()) {
2532 generator.emitReadOnlyExceptionIfNeeded();
2533 return;
2534 }
2535 generator.emitMove(local.get(), value);
2536 return;
2537 }
2538 if (generator.isStrictMode())
2539 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
2540 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), m_boundProperty);
2541 generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
2542 generator.emitPutToScope(scope, m_boundProperty, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
2543 return;
2544}
2545
2546void BindingNode::toString(StringBuilder& builder) const
2547{
2548 builder.append(m_boundProperty.string());
2549}
2550
2551void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2552{
2553 identifiers.append(m_boundProperty);
2554}
2555
2556RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2557{
2558 RELEASE_ASSERT_NOT_REACHED();
2559 return 0;
2560}
f9bf01c6
A
2561
2562} // namespace JSC