]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecompiler/NodesCodegen.cpp
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / bytecompiler / NodesCodegen.cpp
1 /*
2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6 * Copyright (C) 2007 Maks Orlovich
7 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
8 * Copyright (C) 2012 Igalia, S.L.
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
31 #include "BuiltinNames.h"
32 #include "BytecodeGenerator.h"
33 #include "CallFrame.h"
34 #include "Debugger.h"
35 #include "JIT.h"
36 #include "JSFunction.h"
37 #include "JSGlobalObject.h"
38 #include "JSNameScope.h"
39 #include "JSONObject.h"
40 #include "LabelScope.h"
41 #include "Lexer.h"
42 #include "JSCInlines.h"
43 #include "Parser.h"
44 #include "PropertyNameArray.h"
45 #include "RegExpCache.h"
46 #include "RegExpObject.h"
47 #include "SamplingTool.h"
48 #include "StackAlignment.h"
49 #include <wtf/Assertions.h>
50 #include <wtf/RefCountedLeakCounter.h>
51 #include <wtf/Threading.h>
52
53 using namespace WTF;
54
55 namespace 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
80 void 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
89 // ------------------------------ ThrowableExpressionData --------------------------------
90
91 RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const String& message)
92 {
93 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
94 generator.emitThrowReferenceError(message);
95 return generator.newTemporary();
96 }
97
98 // ------------------------------ ConstantNode ----------------------------------
99
100 void ConstantNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
101 {
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);
109
110 // All other cases are unconditional fall-throughs, like "if (true)".
111 }
112
113 RegisterID* ConstantNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
114 {
115 if (dst == generator.ignoredResult())
116 return 0;
117 return generator.emitLoad(dst, jsValue(generator));
118 }
119
120 JSValue StringNode::jsValue(BytecodeGenerator& generator) const
121 {
122 return generator.addStringConstant(m_value);
123 }
124
125 // ------------------------------ RegExpNode -----------------------------------
126
127 RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
128 {
129 if (dst == generator.ignoredResult())
130 return 0;
131 return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.vm(), m_pattern.string(), regExpFlags(m_flags.string())));
132 }
133
134 // ------------------------------ ThisNode -------------------------------------
135
136 RegisterID* 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
145 bool ResolveNode::isPure(BytecodeGenerator& generator) const
146 {
147 return generator.local(m_ident).get();
148 }
149
150 RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
151 {
152 if (Local local = generator.local(m_ident)) {
153 if (dst == generator.ignoredResult())
154 return 0;
155 return generator.moveToDestinationIfNeeded(dst, local.get());
156 }
157
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);
162 }
163
164 // ------------------------------ ArrayNode ------------------------------------
165
166 RegisterID* 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()) {
173 if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
174 break;
175 ++length;
176 }
177
178 if (!firstPutElement && !m_elision)
179 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
180
181 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
182 ElementNode* n = firstPutElement;
183 for (; n; n = n->next()) {
184 if (n->value()->isSpreadExpression())
185 goto handleSpread;
186 RegisterID* value = generator.emitNode(n->value());
187 length += n->elision();
188 generator.emitPutByIndex(array.get(), length++, value);
189 }
190
191 if (m_elision) {
192 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
193 generator.emitPutById(array.get(), generator.propertyNames().length, value);
194 }
195
196 return generator.moveToDestinationIfNeeded(dst, array.get());
197
198 handleSpread:
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());
222 }
223
224 bool 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
235 ArgumentListNode* ArrayNode::toArgumentList(VM* vm, int lineNumber, int startPosition) const
236 {
237 ASSERT(!m_elision && !m_optional);
238 ElementNode* ptr = m_element;
239 if (!ptr)
240 return 0;
241 JSTokenLocation location;
242 location.line = lineNumber;
243 location.startOffset = startPosition;
244 ArgumentListNode* head = new (vm) ArgumentListNode(location, ptr->value());
245 ArgumentListNode* tail = head;
246 ptr = ptr->next();
247 for (; ptr; ptr = ptr->next()) {
248 ASSERT(!ptr->elision());
249 tail = new (vm) ArgumentListNode(location, tail, ptr->value());
250 }
251 return head;
252 }
253
254 // ------------------------------ ObjectLiteralNode ----------------------------
255
256 RegisterID* 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
268 RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
269 {
270 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
271
272 generator.emitNewObject(newObj.get());
273
274 // Fast case: this loop just handles regular value properties.
275 PropertyListNode* p = this;
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 }
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));
298 GetterSetterMap::AddResult result = map.add(node->name()->impl(), pair);
299 if (!result.isNewEntry)
300 result.iterator->value.second = node;
301 }
302
303 // Iterate over the remaining properties in the list.
304 for (; p; p = p->m_next) {
305 PropertyNode* node = p->m_node;
306
307 // Handle regular values.
308 if (node->m_type == PropertyNode::Constant) {
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));
315 continue;
316 }
317
318 RegisterID* value = generator.emitNode(node->m_assign);
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);
322 GetterSetterMap::iterator it = map.find(node->name()->impl());
323 ASSERT(it != map.end());
324 GetterSetterPair& pair = it->value;
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 }
353 }
354
355 generator.emitPutGetterSetter(newObj.get(), *node->name(), getterReg.get(), setterReg.get());
356 }
357 }
358
359 return generator.moveToDestinationIfNeeded(dst, newObj.get());
360 }
361
362 // ------------------------------ BracketAccessorNode --------------------------------
363
364 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
365 {
366 if (m_base->isResolveNode()
367 && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())
368 && !generator.symbolTable().slowArguments()) {
369 RegisterID* property = generator.emitNode(m_subscript);
370 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
371 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
372 }
373
374 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
375 RegisterID* property = generator.emitNode(m_subscript);
376 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
377 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
378 }
379
380 // ------------------------------ DotAccessorNode --------------------------------
381
382 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
383 {
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;
390 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
391 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
392 }
393
394 nonArgumentsPath:
395 RegisterID* base = generator.emitNode(m_base);
396 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
397 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
398 }
399
400 // ------------------------------ ArgumentListNode -----------------------------
401
402 RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
403 {
404 ASSERT(m_expr);
405 return generator.emitNode(dst, m_expr);
406 }
407
408 // ------------------------------ NewExprNode ----------------------------------
409
410 RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
411 {
412 ExpectedFunction expectedFunction;
413 if (m_expr->isResolveNode())
414 expectedFunction = generator.expectedFunctionForIdentifier(static_cast<ResolveNode*>(m_expr)->identifier());
415 else
416 expectedFunction = NoExpectedFunction;
417 RefPtr<RegisterID> func = generator.emitNode(m_expr);
418 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
419 CallArguments callArguments(generator, m_args);
420 return generator.emitConstruct(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
421 }
422
423 CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode, unsigned additionalArguments)
424 : m_argumentsNode(argumentsNode)
425 , m_padding(0)
426 {
427 if (generator.shouldEmitProfileHooks())
428 m_profileHookRegister = generator.newTemporary();
429
430 size_t argumentCountIncludingThis = 1 + additionalArguments; // 'this' register.
431 if (argumentsNode) {
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();
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++;
445 }
446 }
447
448 // ------------------------------ EvalFunctionCallNode ----------------------------------
449
450 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
451 {
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();
460 CallArguments callArguments(generator, m_args);
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());
466 }
467
468 // ------------------------------ FunctionCallValueNode ----------------------------------
469
470 RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
471 {
472 RefPtr<RegisterID> func = generator.emitNode(m_expr);
473 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
474 CallArguments callArguments(generator, m_args);
475 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
476 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
477 }
478
479 // ------------------------------ FunctionCallResolveNode ----------------------------------
480
481 RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
482 {
483 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident);
484
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());
488 CallArguments callArguments(generator, m_args);
489 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
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.
492 return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
493 }
494
495 RefPtr<RegisterID> func = generator.newTemporary();
496 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
497 CallArguments callArguments(generator, m_args);
498
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());
504 }
505
506 // ------------------------------ FunctionCallBracketNode ----------------------------------
507
508 RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
509 {
510 RefPtr<RegisterID> base = generator.emitNode(m_base);
511 RegisterID* property = generator.emitNode(m_subscript);
512 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
513 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
514 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
515 CallArguments callArguments(generator, m_args);
516 generator.emitMove(callArguments.thisRegister(), base.get());
517 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
518 }
519
520 // ------------------------------ FunctionCallDotNode ----------------------------------
521
522 RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
523 {
524 RefPtr<RegisterID> function = generator.tempDestination(dst);
525 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
526 CallArguments callArguments(generator, m_args);
527 generator.emitNode(callArguments.thisRegister(), m_base);
528 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
529 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
530 return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
531 }
532
533 static 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;
542 }
543
544 RegisterID* 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);
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);
557 {
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) {
575 ArgumentListNode* oldList = m_args->m_listNode;
576 m_args->m_listNode = m_args->m_listNode->m_next;
577
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);
581 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
582 m_args->m_listNode = oldList;
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());
587 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
588 }
589 }
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());
599 }
600 return returnValue.get();
601 }
602
603 static 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
609 RegisterID* 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);
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());
667 } else {
668 m_args->m_listNode = m_args->m_listNode->m_next;
669 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
670 CallArguments callArguments(generator, m_args);
671 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
672 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
673 }
674 m_args->m_listNode = oldList;
675 } else {
676 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
677 CallArguments callArguments(generator, m_args);
678 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
679 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
680 }
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());
701 }
702 if (emitCallCheck) {
703 generator.emitJump(end.get());
704 generator.emitLabel(realCall.get());
705 CallArguments callArguments(generator, m_args);
706 generator.emitMove(callArguments.thisRegister(), base.get());
707 generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
708 generator.emitLabel(end.get());
709 }
710 return returnValue.get();
711 }
712
713 // ------------------------------ PostfixNode ----------------------------------
714
715 static RegisterID* emitIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
716 {
717 return (oper == OpPlusPlus) ? generator.emitInc(srcDst) : generator.emitDec(srcDst);
718 }
719
720 static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
721 {
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());
727 }
728
729 RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
730 {
731 if (dst == generator.ignoredResult())
732 return PrefixNode::emitResolve(generator, dst);
733
734 ASSERT(m_expr->isResolveNode());
735 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
736 const Identifier& ident = resolve->identifier();
737
738 if (Local local = generator.local(ident)) {
739 RegisterID* localReg = local.get();
740 if (local.isReadOnly()) {
741 generator.emitReadOnlyExceptionIfNeeded();
742 localReg = generator.emitMove(generator.tempDestination(dst), localReg);
743 } else if (local.isCaptured()) {
744 RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
745 ASSERT(dst != localReg);
746 RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
747 generator.emitToNumber(tempDst.get(), localReg);
748 generator.emitMove(tempDstSrc.get(), localReg);
749 emitIncOrDec(generator, tempDstSrc.get(), m_operator);
750 generator.emitMove(localReg, tempDstSrc.get());
751 return tempDst.get();
752 }
753 return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg, m_operator);
754 }
755
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);
759 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
760 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
761 return oldValue.get();
762 }
763
764 RegisterID* PostfixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
765 {
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);
776
777 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
778 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
779 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
780 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
781 generator.emitPutByVal(base.get(), property.get(), value.get());
782 return generator.moveToDestinationIfNeeded(dst, oldValue);
783 }
784
785 RegisterID* PostfixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
786 {
787 if (dst == generator.ignoredResult())
788 return PrefixNode::emitDot(generator, dst);
789
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);
796
797 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
798 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), ident);
799 RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
800 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
801 generator.emitPutById(base.get(), ident, value.get());
802 return generator.moveToDestinationIfNeeded(dst, oldValue);
803 }
804
805 RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
806 {
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
816 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
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
823 RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
824 {
825 if (generator.local(m_ident).get())
826 return generator.emitLoad(generator.finalDestination(dst), false);
827
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);
831 }
832
833 // ------------------------------ DeleteBracketNode -----------------------------------
834
835 RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
836 {
837 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
838 RegisterID* r1 = generator.emitNode(m_subscript);
839
840 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
841 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
842 }
843
844 // ------------------------------ DeleteDotNode -----------------------------------
845
846 RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
847 {
848 RegisterID* r0 = generator.emitNode(m_base);
849
850 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
851 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
852 }
853
854 // ------------------------------ DeleteValueNode -----------------------------------
855
856 RegisterID* 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
866 RegisterID* 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
878 RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
879 {
880 if (Local local = generator.local(m_ident)) {
881 if (dst == generator.ignoredResult())
882 return 0;
883 return generator.emitTypeOf(generator.finalDestination(dst), local.get());
884 }
885
886 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
887 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound);
888 if (dst == generator.ignoredResult())
889 return 0;
890 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get());
891 }
892
893 // ------------------------------ TypeOfValueNode -----------------------------------
894
895 RegisterID* 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
905 // ------------------------------ PrefixNode ----------------------------------
906
907 RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* dst)
908 {
909 ASSERT(m_expr->isResolveNode());
910 ResolveNode* resolve = static_cast<ResolveNode*>(m_expr);
911 const Identifier& ident = resolve->identifier();
912
913 if (Local local = generator.local(ident)) {
914 RegisterID* localReg = local.get();
915 if (local.isReadOnly()) {
916 generator.emitReadOnlyExceptionIfNeeded();
917 localReg = generator.emitMove(generator.tempDestination(dst), localReg);
918 } else if (local.isCaptured()) {
919 RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
920 generator.emitMove(tempDst.get(), localReg);
921 emitIncOrDec(generator, tempDst.get(), m_operator);
922 generator.emitMove(localReg, tempDst.get());
923 return generator.moveToDestinationIfNeeded(dst, tempDst.get());
924 }
925 emitIncOrDec(generator, localReg, m_operator);
926 return generator.moveToDestinationIfNeeded(dst, localReg);
927 }
928
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());
935 }
936
937 RegisterID* PrefixNode::emitBracket(BytecodeGenerator& generator, RegisterID* dst)
938 {
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);
946 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
947
948 generator.emitExpressionInfo(bracketAccessor->divot(), bracketAccessor->divotStart(), bracketAccessor->divotEnd());
949 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
950 emitIncOrDec(generator, value, m_operator);
951 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
952 generator.emitPutByVal(base.get(), property.get(), value);
953 return generator.moveToDestinationIfNeeded(dst, propDst.get());
954 }
955
956 RegisterID* PrefixNode::emitDot(BytecodeGenerator& generator, RegisterID* dst)
957 {
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);
964 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
965
966 generator.emitExpressionInfo(dotAccessor->divot(), dotAccessor->divotStart(), dotAccessor->divotEnd());
967 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), ident);
968 emitIncOrDec(generator, value, m_operator);
969 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
970 generator.emitPutById(base.get(), ident, value);
971 return generator.moveToDestinationIfNeeded(dst, propDst.get());
972 }
973
974 RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
975 {
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
985 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
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
992 RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
993 {
994 RegisterID* src = generator.emitNode(m_expr);
995 generator.emitExpressionInfo(position(), position(), position());
996 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
997 }
998
999 // ------------------------------ BitwiseNotNode -----------------------------------
1000
1001 RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1002 {
1003 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
1004 RegisterID* src1 = generator.emitNode(m_expr);
1005 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
1006 }
1007
1008 // ------------------------------ LogicalNotNode -----------------------------------
1009
1010 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1011 {
1012 // reverse the true and false targets
1013 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, invert(fallThroughMode));
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 //
1047 RegisterID* 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)
1127 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->divotStart(), emitExpressionInfoForMe->divotEnd());
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
1136 void 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
1150 static 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
1164 void 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
1194 RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1195 {
1196 OpcodeID opcodeID = this->opcodeID();
1197
1198 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) {
1199 generator.emitExpressionInfo(position(), position(), position());
1200 return emitStrcat(generator, dst);
1201 }
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
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;
1220 RegisterID* src2 = generator.emitNode(right);
1221 generator.emitExpressionInfo(position(), position(), position());
1222 if (wasTypeof && (opcodeID == op_neq || opcodeID == op_nstricteq)) {
1223 RefPtr<RegisterID> tmp = generator.tempDestination(dst);
1224 if (opcodeID == op_neq)
1225 generator.emitEqualityOp(op_eq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1226 else if (opcodeID == op_nstricteq)
1227 generator.emitEqualityOp(op_stricteq, generator.finalDestination(tmp.get(), src1.get()), src1.get(), src2);
1228 else
1229 RELEASE_ASSERT_NOT_REACHED();
1230 return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
1231 }
1232 RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(left->resultDescriptor(), right->resultDescriptor()));
1233 if (opcodeID == op_urshift && dst != generator.ignoredResult())
1234 return generator.emitUnaryOp(op_unsigned, result, result);
1235 return result;
1236 }
1237
1238 RegisterID* 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
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));
1252 RegisterID* src2 = generator.emitNode(right);
1253 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1254 }
1255
1256 RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1257 {
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));
1264 RegisterID* src2 = generator.emitNode(right);
1265 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1266 }
1267
1268 RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1269 {
1270 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1271 RegisterID* src2 = generator.emitNode(m_expr2);
1272 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1273 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1274 }
1275
1276 RegisterID* 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);
1280 RefPtr<RegisterID> prototype = generator.newTemporary();
1281 RefPtr<RegisterID> dstReg = generator.finalDestination(dst, src1.get());
1282 RefPtr<Label> target = generator.newLabel();
1283
1284 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1285 generator.emitCheckHasInstance(dstReg.get(), src1.get(), src2.get(), target.get());
1286
1287 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1288 generator.emitGetById(prototype.get(), src2.get(), generator.vm()->propertyNames->prototype);
1289
1290 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1291 RegisterID* result = generator.emitInstanceOf(dstReg.get(), src1.get(), prototype.get());
1292 generator.emitLabel(target.get());
1293 return result;
1294 }
1295
1296 // ------------------------------ LogicalOpNode ----------------------------
1297
1298 RegisterID* 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
1314 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
1315 {
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());
1322
1323 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMode);
1324 }
1325
1326 // ------------------------------ ConditionalNode ------------------------------
1327
1328 RegisterID* 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
1334 RefPtr<Label> beforeThen = generator.newLabel();
1335 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), FallThroughMeansTrue);
1336 generator.emitLabel(beforeThen.get());
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?
1352 static 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:
1392 RELEASE_ASSERT_NOT_REACHED();
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)
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;
1406 }
1407
1408 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1409 {
1410 if (Local local = generator.local(m_ident)) {
1411 if (local.isReadOnly()) {
1412 generator.emitReadOnlyExceptionIfNeeded();
1413 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1414 }
1415
1416 if (local.isCaptured()
1417 || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1418 RefPtr<RegisterID> result = generator.newTemporary();
1419 generator.emitMove(result.get(), local.get());
1420 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1421 generator.emitMove(local.get(), result.get());
1422 return generator.moveToDestinationIfNeeded(dst, result.get());
1423 }
1424
1425 RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1426 return generator.moveToDestinationIfNeeded(dst, result);
1427 }
1428
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);
1435 }
1436
1437 // ------------------------------ AssignResolveNode -----------------------------------
1438
1439 RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1440 {
1441 if (Local local = generator.local(m_ident)) {
1442 if (local.isReadOnly()) {
1443 generator.emitReadOnlyExceptionIfNeeded();
1444 return generator.emitNode(dst, m_right);
1445 }
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);
1453 return generator.moveToDestinationIfNeeded(dst, result);
1454 }
1455
1456 if (generator.isStrictMode())
1457 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1458 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1459 if (dst == generator.ignoredResult())
1460 dst = 0;
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);
1464 }
1465
1466 // ------------------------------ AssignDotNode -----------------------------------
1467
1468 RegisterID* 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);
1472 RegisterID* result = generator.emitNode(value.get(), m_right);
1473 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1474 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1475 generator.emitPutById(base.get(), m_ident, forwardResult);
1476 return generator.moveToDestinationIfNeeded(dst, forwardResult);
1477 }
1478
1479 // ------------------------------ ReadModifyDotNode -----------------------------------
1480
1481 RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1482 {
1483 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1484
1485 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1486 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
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()));
1488
1489 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1490 return generator.emitPutById(base.get(), m_ident, updatedValue);
1491 }
1492
1493 // ------------------------------ AssignErrorNode -----------------------------------
1494
1495 RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1496 {
1497 return emitThrowReferenceError(generator, "Left side of assignment is not a reference.");
1498 }
1499
1500 // ------------------------------ AssignBracketNode -----------------------------------
1501
1502 RegisterID* 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);
1507 RegisterID* result = generator.emitNode(value.get(), m_right);
1508
1509 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1510 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1511 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1512 return generator.moveToDestinationIfNeeded(dst, forwardResult);
1513 }
1514
1515 // ------------------------------ ReadModifyBracketNode -----------------------------------
1516
1517 RegisterID* 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
1522 generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
1523 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
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()));
1525
1526 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
1527 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1528
1529 return updatedValue;
1530 }
1531
1532 // ------------------------------ CommaNode ------------------------------------
1533
1534 RegisterID* 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
1544 RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1545 {
1546 // FIXME: This code does not match the behavior of const in Firefox.
1547 if (Local local = generator.constLocal(m_ident)) {
1548 if (!m_init)
1549 return local.get();
1550
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);
1558 }
1559
1560 RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1561
1562 if (generator.codeType() == GlobalCode)
1563 return generator.emitInitGlobalConst(m_ident, value.get());
1564
1565 if (generator.codeType() != EvalCode)
1566 return value.get();
1567
1568 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope.
1569 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
1570 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound);
1571 }
1572
1573 RegisterID* 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
1584 void ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1585 {
1586 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1587 generator.emitNode(m_next);
1588 }
1589
1590 // ------------------------------ SourceElements -------------------------------
1591
1592
1593 inline StatementNode* SourceElements::lastStatement() const
1594 {
1595 size_t size = m_statements.size();
1596 return size ? m_statements[size - 1] : 0;
1597 }
1598
1599 inline 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
1608 inline StatementNode* BlockNode::lastStatement() const
1609 {
1610 return m_statements ? m_statements->lastStatement() : 0;
1611 }
1612
1613 inline StatementNode* BlockNode::singleStatement() const
1614 {
1615 return m_statements ? m_statements->singleStatement() : 0;
1616 }
1617
1618 void BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1619 {
1620 if (!m_statements)
1621 return;
1622 m_statements->emitBytecode(generator, dst);
1623 }
1624
1625 // ------------------------------ EmptyStatementNode ---------------------------
1626
1627 void EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1628 {
1629 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1630 }
1631
1632 // ------------------------------ DebuggerStatementNode ---------------------------
1633
1634 void DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1635 {
1636 generator.emitDebugHook(DidReachBreakpoint, lastLine(), startOffset(), lineStartOffset());
1637 }
1638
1639 // ------------------------------ ExprStatementNode ----------------------------
1640
1641 void ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1642 {
1643 ASSERT(m_expr);
1644 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1645 generator.emitNode(dst, m_expr);
1646 }
1647
1648 // ------------------------------ VarStatementNode ----------------------------
1649
1650 void VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1651 {
1652 ASSERT(m_expr);
1653 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1654 generator.emitNode(m_expr);
1655 }
1656
1657 // ------------------------------ IfElseNode ---------------------------------------
1658
1659 static inline StatementNode* singleStatement(StatementNode* statementNode)
1660 {
1661 if (statementNode->isBlock())
1662 return static_cast<BlockNode*>(statementNode)->singleStatement();
1663 return statementNode;
1664 }
1665
1666 bool 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;
1681 }
1682
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 }
1692
1693 return false;
1694 }
1695
1696 void IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1697 {
1698 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1699
1700 RefPtr<Label> beforeThen = generator.newLabel();
1701 RefPtr<Label> beforeElse = generator.newLabel();
1702 RefPtr<Label> afterElse = generator.newLabel();
1703
1704 Label* trueTarget = beforeThen.get();
1705 Label* falseTarget = beforeElse.get();
1706 FallThroughMode fallThroughMode = FallThroughMeansTrue;
1707 bool didFoldIfBlock = tryFoldBreakAndContinue(generator, m_ifBlock, trueTarget, fallThroughMode);
1708
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 }
1717
1718 generator.emitLabel(beforeElse.get());
1719
1720 if (m_elseBlock)
1721 generator.emitNode(dst, m_elseBlock);
1722
1723 generator.emitLabel(afterElse.get());
1724 }
1725
1726 // ------------------------------ DoWhileNode ----------------------------------
1727
1728 void DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1729 {
1730 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1731
1732 RefPtr<Label> topOfLoop = generator.newLabel();
1733 generator.emitLabel(topOfLoop.get());
1734 generator.emitLoopHint();
1735 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
1736
1737 generator.emitNode(dst, m_statement);
1738
1739 generator.emitLabel(scope->continueTarget());
1740 generator.emitDebugHook(WillExecuteStatement, lastLine(), startOffset(), lineStartOffset());
1741 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1742
1743 generator.emitLabel(scope->breakTarget());
1744 }
1745
1746 // ------------------------------ WhileNode ------------------------------------
1747
1748 void WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1749 {
1750 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1751 RefPtr<Label> topOfLoop = generator.newLabel();
1752
1753 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->startOffset(), m_expr->lineStartOffset());
1754 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
1755
1756 generator.emitLabel(topOfLoop.get());
1757 generator.emitLoopHint();
1758
1759 generator.emitNode(dst, m_statement);
1760
1761 generator.emitLabel(scope->continueTarget());
1762 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1763
1764 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1765
1766 generator.emitLabel(scope->breakTarget());
1767 }
1768
1769 // ------------------------------ ForNode --------------------------------------
1770
1771 void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1772 {
1773 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1774
1775 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1776
1777 if (m_expr1)
1778 generator.emitNode(generator.ignoredResult(), m_expr1);
1779
1780 RefPtr<Label> topOfLoop = generator.newLabel();
1781 if (m_expr2)
1782 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansTrue);
1783
1784 generator.emitLabel(topOfLoop.get());
1785 generator.emitLoopHint();
1786
1787 generator.emitNode(dst, m_statement);
1788
1789 generator.emitLabel(scope->continueTarget());
1790 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1791 if (m_expr3)
1792 generator.emitNode(generator.ignoredResult(), m_expr3);
1793
1794 if (m_expr2)
1795 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), FallThroughMeansFalse);
1796 else
1797 generator.emitJump(topOfLoop.get());
1798
1799 generator.emitLabel(scope->breakTarget());
1800 }
1801
1802 // ------------------------------ ForInNode ------------------------------------
1803
1804 void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1805 {
1806 LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
1807
1808 if (!m_lexpr->isAssignmentLocation()) {
1809 emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
1810 return;
1811 }
1812
1813 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
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());
1825 generator.emitLoopHint();
1826
1827 RegisterID* propertyName;
1828 bool optimizedForinAccess = false;
1829 if (m_lexpr->isResolveNode()) {
1830 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1831 Local local = generator.local(ident);
1832 if (!local.get()) {
1833 propertyName = generator.newTemporary();
1834 RefPtr<RegisterID> protect = propertyName;
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);
1840 } else {
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());
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
1854 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1855 generator.emitPutById(base, ident, propertyName);
1856 } else if (m_lexpr->isBracketAccessorNode()) {
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
1863 generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
1864 generator.emitPutByVal(base.get(), subscript, propertyName);
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 }
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());
1897 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1898 generator.emitLabel(scope->breakTarget());
1899 }
1900
1901 // ------------------------------ ForOfNode ------------------------------------
1902 void 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
1949 // ------------------------------ ContinueNode ---------------------------------
1950
1951 Label* ContinueNode::trivialTarget(BytecodeGenerator& generator)
1952 {
1953 if (generator.shouldEmitDebugHooks())
1954 return 0;
1955
1956 LabelScopePtr scope = generator.continueTarget(m_ident);
1957 ASSERT(scope);
1958
1959 if (generator.scopeDepth() != scope->scopeDepth())
1960 return 0;
1961
1962 return scope->continueTarget();
1963 }
1964
1965 void ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1966 {
1967 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1968
1969 LabelScopePtr scope = generator.continueTarget(m_ident);
1970 ASSERT(scope);
1971
1972 generator.emitPopScopes(scope->scopeDepth());
1973 generator.emitJump(scope->continueTarget());
1974 }
1975
1976 // ------------------------------ BreakNode ------------------------------------
1977
1978 Label* BreakNode::trivialTarget(BytecodeGenerator& generator)
1979 {
1980 if (generator.shouldEmitDebugHooks())
1981 return 0;
1982
1983 LabelScopePtr scope = generator.breakTarget(m_ident);
1984 ASSERT(scope);
1985
1986 if (generator.scopeDepth() != scope->scopeDepth())
1987 return 0;
1988
1989 return scope->breakTarget();
1990 }
1991
1992 void BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1993 {
1994 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
1995
1996 LabelScopePtr scope = generator.breakTarget(m_ident);
1997 ASSERT(scope);
1998
1999 generator.emitPopScopes(scope->scopeDepth());
2000 generator.emitJump(scope->breakTarget());
2001 }
2002
2003 // ------------------------------ ReturnNode -----------------------------------
2004
2005 void ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2006 {
2007 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2008 ASSERT(generator.codeType() == FunctionCode);
2009
2010 if (dst == generator.ignoredResult())
2011 dst = 0;
2012
2013 RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
2014 if (generator.scopeDepth()) {
2015 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
2016 generator.emitPopScopes(0);
2017 }
2018
2019 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
2020 generator.emitReturn(returnRegister.get());
2021 }
2022
2023 // ------------------------------ WithNode -------------------------------------
2024
2025 void WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2026 {
2027 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2028
2029 RefPtr<RegisterID> scope = generator.emitNode(m_expr);
2030 generator.emitExpressionInfo(m_divot, m_divot - m_expressionLength, m_divot);
2031 generator.emitPushWithScope(scope.get());
2032 generator.emitNode(dst, m_statement);
2033 generator.emitPopScope();
2034 }
2035
2036 // ------------------------------ CaseClauseNode --------------------------------
2037
2038 inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2039 {
2040 if (!m_statements)
2041 return;
2042 m_statements->emitBytecode(generator, dst);
2043 }
2044
2045 // ------------------------------ CaseBlockNode --------------------------------
2046
2047 enum SwitchKind {
2048 SwitchUnset = 0,
2049 SwitchNumber = 1,
2050 SwitchString = 2,
2051 SwitchNeither = 3
2052 };
2053
2054 static 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 }
2078 const String& value = static_cast<StringNode*>(clauseExpression)->value().string();
2079 if (singleCharacterSwitch &= value.length() == 1) {
2080 int32_t intVal = value[0];
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 }
2093
2094 static inline size_t length(ClauseListNode* list1, ClauseListNode* list2)
2095 {
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
2104 SwitchInfo::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
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
2136 void CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
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();
2143 SwitchInfo::SwitchType switchType = tryTableSwitch(literalVector, min_num, max_num);
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
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 }
2195 }
2196
2197 // ------------------------------ SwitchNode -----------------------------------
2198
2199 void SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2200 {
2201 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2202
2203 LabelScopePtr scope = generator.newLabelScope(LabelScope::Switch);
2204
2205 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
2206 m_block->emitBytecodeForBlock(generator, r0.get(), dst);
2207
2208 generator.emitLabel(scope->breakTarget());
2209 }
2210
2211 // ------------------------------ LabelNode ------------------------------------
2212
2213 void LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2214 {
2215 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2216
2217 ASSERT(!generator.breakTarget(m_name));
2218
2219 LabelScopePtr scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
2220 generator.emitNode(dst, m_statement);
2221
2222 generator.emitLabel(scope->breakTarget());
2223 }
2224
2225 // ------------------------------ ThrowNode ------------------------------------
2226
2227 void ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2228 {
2229 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2230
2231 if (dst == generator.ignoredResult())
2232 dst = 0;
2233 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
2234 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
2235 generator.emitThrow(expr.get());
2236 }
2237
2238 // ------------------------------ TryNode --------------------------------------
2239
2240 void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
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
2245 generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
2246
2247 ASSERT(m_catchBlock || m_finallyBlock);
2248
2249 RefPtr<Label> tryStartLabel = generator.newLabel();
2250 generator.emitLabel(tryStartLabel.get());
2251
2252 if (m_finallyBlock)
2253 generator.pushFinallyContext(m_finallyBlock);
2254 TryData* tryData = generator.pushTry(tryStartLabel.get());
2255
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());
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
2274 generator.emitPushCatchScope(m_exceptionIdent, exceptionRegister.get(), DontDelete);
2275 generator.emitNode(dst, m_catchBlock);
2276 generator.emitPopScope();
2277 generator.emitLabel(catchEndLabel.get());
2278 }
2279
2280 if (m_finallyBlock) {
2281 RefPtr<Label> preFinallyLabel = generator.emitLabel(generator.newLabel().get());
2282
2283 generator.popFinallyContext();
2284
2285 RefPtr<Label> finallyEndLabel = generator.newLabel();
2286
2287 // Normal path: run the finally code, and jump to the end.
2288 generator.emitNode(dst, m_finallyBlock);
2289 generator.emitJump(finallyEndLabel.get());
2290
2291 // Uncaught exception path: invoke the finally block, then re-throw the exception.
2292 RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
2293 generator.emitNode(dst, m_finallyBlock);
2294 generator.emitThrow(tempExceptionRegister.get());
2295
2296 generator.emitLabel(finallyEndLabel.get());
2297 }
2298 }
2299
2300 // ------------------------------ ScopeNode -----------------------------
2301
2302 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2303 {
2304 if (!m_statements)
2305 return;
2306 m_statements->emitBytecode(generator, dst);
2307 }
2308
2309 // ------------------------------ ProgramNode -----------------------------
2310
2311 void ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2312 {
2313 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
2314
2315 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2316 generator.emitLoad(dstRegister.get(), jsUndefined());
2317 emitStatementsBytecode(generator, dstRegister.get());
2318
2319 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
2320 generator.emitEnd(dstRegister.get());
2321 }
2322
2323 // ------------------------------ EvalNode -----------------------------
2324
2325 void EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2326 {
2327 generator.emitDebugHook(WillExecuteProgram, startLine(), startStartOffset(), startLineStartOffset());
2328
2329 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2330 generator.emitLoad(dstRegister.get(), jsUndefined());
2331 emitStatementsBytecode(generator, dstRegister.get());
2332
2333 generator.emitDebugHook(DidExecuteProgram, lastLine(), startOffset(), lineStartOffset());
2334 generator.emitEnd(dstRegister.get());
2335 }
2336
2337 // ------------------------------ FunctionBodyNode -----------------------------
2338
2339 void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2340 {
2341 generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
2342 emitStatementsBytecode(generator, generator.ignoredResult());
2343
2344 StatementNode* singleStatement = this->singleStatement();
2345 ReturnNode* returnNode = 0;
2346
2347 // Check for a return statement at the end of a function composed of a single block.
2348 if (singleStatement && singleStatement->isBlock()) {
2349 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2350 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
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());
2357 ASSERT(startOffset() >= lineStartOffset());
2358 generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
2359 generator.emitReturn(r0);
2360 return;
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();
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);
2375 }
2376 }
2377 }
2378 }
2379
2380 // ------------------------------ FuncDeclNode ---------------------------------
2381
2382 void FuncDeclNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2383 {
2384 }
2385
2386 // ------------------------------ FuncExprNode ---------------------------------
2387
2388 RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2389 {
2390 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
2391 }
2392
2393 // ------------------------------ DeconstructingAssignmentNode -----------------
2394 RegisterID* 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
2404 DeconstructionPatternNode::~DeconstructionPatternNode()
2405 {
2406 }
2407
2408 void 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
2421 RegisterID* 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
2471 void 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
2486 void 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
2494 void 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
2512 void 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
2522 void 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
2528 void 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
2546 void BindingNode::toString(StringBuilder& builder) const
2547 {
2548 builder.append(m_boundProperty.string());
2549 }
2550
2551 void BindingNode::collectBoundIdentifiers(Vector<Identifier>& identifiers) const
2552 {
2553 identifiers.append(m_boundProperty);
2554 }
2555
2556 RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
2557 {
2558 RELEASE_ASSERT_NOT_REACHED();
2559 return 0;
2560 }
2561
2562 } // namespace JSC