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