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 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.
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.
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.
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.
29 #include "NodeConstructors.h"
31 #include "BytecodeGenerator.h"
32 #include "CallFrame.h"
35 #include "JSFunction.h"
36 #include "JSGlobalObject.h"
37 #include "JSStaticScopeObject.h"
38 #include "LabelScope.h"
40 #include "Operations.h"
42 #include "PropertyNameArray.h"
43 #include "RegExpCache.h"
44 #include "RegExpObject.h"
45 #include "SamplingTool.h"
46 #include "UStringConcatenate.h"
47 #include <wtf/Assertions.h>
48 #include <wtf/RefCountedLeakCounter.h>
49 #include <wtf/Threading.h>
56 Details of the emitBytecode function.
58 Return value: The register holding the production's value.
59 dst: An optional parameter specifying the most efficient destination at
60 which to store the production's value. The callee must honor dst.
62 The dst argument provides for a crude form of copy propagation. For example,
75 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
78 // ------------------------------ ThrowableExpressionData --------------------------------
80 RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const UString& message)
82 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
83 generator.emitThrowReferenceError(message);
84 return generator.newTemporary();
87 // ------------------------------ NullNode -------------------------------------
89 RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
91 if (dst == generator.ignoredResult())
93 return generator.emitLoad(dst, jsNull());
96 // ------------------------------ BooleanNode ----------------------------------
98 RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
100 if (dst == generator.ignoredResult())
102 return generator.emitLoad(dst, m_value);
105 // ------------------------------ NumberNode -----------------------------------
107 RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
109 if (dst == generator.ignoredResult())
111 return generator.emitLoad(dst, m_value);
114 // ------------------------------ StringNode -----------------------------------
116 RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
118 if (dst == generator.ignoredResult())
120 return generator.emitLoad(dst, m_value);
123 // ------------------------------ RegExpNode -----------------------------------
125 RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
127 if (dst == generator.ignoredResult())
129 return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(*generator.globalData(), m_pattern.ustring(), regExpFlags(m_flags.ustring())));
132 // ------------------------------ ThisNode -------------------------------------
134 RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
136 if (dst == generator.ignoredResult())
138 return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
141 // ------------------------------ ResolveNode ----------------------------------
143 bool ResolveNode::isPure(BytecodeGenerator& generator) const
145 return generator.resolve(m_ident).isStatic();
148 RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
150 ResolveResult resolveResult = generator.resolve(m_ident);
151 if (RegisterID* local = resolveResult.local()) {
152 if (dst == generator.ignoredResult())
154 return generator.moveToDestinationIfNeeded(dst, local);
157 generator.emitExpressionInfo(m_startOffset + m_ident.length(), m_ident.length(), 0);
158 return generator.emitResolve(generator.finalDestination(dst), resolveResult, m_ident);
161 // ------------------------------ ArrayNode ------------------------------------
163 RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
165 // FIXME: Should we put all of this code into emitNewArray?
168 ElementNode* firstPutElement;
169 for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) {
170 if (firstPutElement->elision())
175 if (!firstPutElement && !m_elision)
176 return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
178 RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
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);
187 RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
188 generator.emitPutById(array.get(), generator.propertyNames().length, value);
191 return generator.moveToDestinationIfNeeded(dst, array.get());
194 bool ArrayNode::isSimpleArray() const
196 if (m_elision || m_optional)
198 for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
205 ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData, int lineNumber) const
207 ASSERT(!m_elision && !m_optional);
208 ElementNode* ptr = m_element;
211 ArgumentListNode* head = new (globalData) ArgumentListNode(lineNumber, ptr->value());
212 ArgumentListNode* tail = head;
214 for (; ptr; ptr = ptr->next()) {
215 ASSERT(!ptr->elision());
216 tail = new (globalData) ArgumentListNode(lineNumber, tail, ptr->value());
221 // ------------------------------ ObjectLiteralNode ----------------------------
223 RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
226 if (dst == generator.ignoredResult())
228 return generator.emitNewObject(generator.finalDestination(dst));
230 return generator.emitNode(dst, m_list);
233 // ------------------------------ PropertyListNode -----------------------------
235 RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
237 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
239 generator.emitNewObject(newObj.get());
241 // Fast case: this loop just handles regular value properties.
242 PropertyListNode* p = this;
243 for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next)
244 generator.emitDirectPutById(newObj.get(), p->m_node->name(), generator.emitNode(p->m_node->m_assign));
246 // Were there any get/set properties?
248 typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
249 typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap;
252 // Build a map, pairing get/set values together.
253 for (PropertyListNode* q = p; q; q = q->m_next) {
254 PropertyNode* node = q->m_node;
255 if (node->m_type == PropertyNode::Constant)
258 GetterSetterPair pair(node, static_cast<PropertyNode*>(0));
259 GetterSetterMap::AddResult result = map.add(node->name().impl(), pair);
260 if (!result.isNewEntry)
261 result.iterator->second.second = node;
264 // Iterate over the remaining properties in the list.
265 for (; p; p = p->m_next) {
266 PropertyNode* node = p->m_node;
267 RegisterID* value = generator.emitNode(node->m_assign);
269 // Handle regular values.
270 if (node->m_type == PropertyNode::Constant) {
271 generator.emitDirectPutById(newObj.get(), node->name(), value);
275 // This is a get/set property, find its entry in the map.
276 ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter);
277 GetterSetterMap::iterator it = map.find(node->name().impl());
278 ASSERT(it != map.end());
279 GetterSetterPair& pair = it->second;
281 // Was this already generated as a part of its partner?
282 if (pair.second == node)
285 // Generate the paired node now.
286 RefPtr<RegisterID> getterReg;
287 RefPtr<RegisterID> setterReg;
289 if (node->m_type == PropertyNode::Getter) {
292 ASSERT(pair.second->m_type == PropertyNode::Setter);
293 setterReg = generator.emitNode(pair.second->m_assign);
295 setterReg = generator.newTemporary();
296 generator.emitLoad(setterReg.get(), jsUndefined());
299 ASSERT(node->m_type == PropertyNode::Setter);
302 ASSERT(pair.second->m_type == PropertyNode::Getter);
303 getterReg = generator.emitNode(pair.second->m_assign);
305 getterReg = generator.newTemporary();
306 generator.emitLoad(getterReg.get(), jsUndefined());
310 generator.emitPutGetterSetter(newObj.get(), node->name(), getterReg.get(), setterReg.get());
314 return generator.moveToDestinationIfNeeded(dst, newObj.get());
317 // ------------------------------ BracketAccessorNode --------------------------------
319 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
321 if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())) {
322 RegisterID* property = generator.emitNode(m_subscript);
323 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
324 return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
327 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
328 RegisterID* property = generator.emitNode(m_subscript);
329 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
330 return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
333 // ------------------------------ DotAccessorNode --------------------------------
335 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
337 if (m_ident == generator.propertyNames().length) {
338 if (!m_base->isResolveNode())
339 goto nonArgumentsPath;
340 ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
341 if (!generator.willResolveToArguments(resolveNode->identifier()))
342 goto nonArgumentsPath;
343 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
344 return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
348 RegisterID* base = generator.emitNode(m_base);
349 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
350 return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
353 // ------------------------------ ArgumentListNode -----------------------------
355 RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
358 return generator.emitNode(dst, m_expr);
361 // ------------------------------ NewExprNode ----------------------------------
363 RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
365 RefPtr<RegisterID> func = generator.emitNode(m_expr);
366 CallArguments callArguments(generator, m_args);
367 return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset());
370 inline CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
371 : m_argumentsNode(argumentsNode)
373 if (generator.shouldEmitProfileHooks())
374 m_profileHookRegister = generator.newTemporary();
376 size_t argumentCountIncludingThis = 1; // 'this' register.
378 for (ArgumentListNode* node = argumentsNode->m_listNode; node; node = node->m_next)
379 ++argumentCountIncludingThis;
382 m_argv.grow(argumentCountIncludingThis);
383 for (int i = argumentCountIncludingThis - 1; i >= 0; --i) {
384 m_argv[i] = generator.newTemporary();
385 ASSERT(static_cast<size_t>(i) == m_argv.size() - 1 || m_argv[i]->index() == m_argv[i + 1]->index() + 1);
389 inline void CallArguments::newArgument(BytecodeGenerator& generator)
391 RefPtr<RegisterID> tmp = generator.newTemporary();
392 ASSERT(m_argv.isEmpty() || tmp->index() == m_argv.last()->index() + 1); // Calling convention assumes that all arguments are contiguous.
393 m_argv.append(tmp.release());
396 // ------------------------------ EvalFunctionCallNode ----------------------------------
398 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
400 RefPtr<RegisterID> func = generator.tempDestination(dst);
401 CallArguments callArguments(generator, m_args);
402 generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
403 generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.resolve(generator.propertyNames().eval), generator.propertyNames().eval);
404 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
407 // ------------------------------ FunctionCallValueNode ----------------------------------
409 RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
411 RefPtr<RegisterID> func = generator.emitNode(m_expr);
412 CallArguments callArguments(generator, m_args);
413 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
414 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
417 // ------------------------------ FunctionCallResolveNode ----------------------------------
419 RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
421 ResolveResult resolveResult = generator.resolve(m_ident);
423 if (RegisterID* local = resolveResult.local()) {
424 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
425 CallArguments callArguments(generator, m_args);
426 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
427 return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), callArguments, divot(), startOffset(), endOffset());
430 if (resolveResult.isStatic()) {
431 RefPtr<RegisterID> func = generator.newTemporary();
432 CallArguments callArguments(generator, m_args);
433 generator.emitGetStaticVar(func.get(), resolveResult);
434 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
435 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
438 RefPtr<RegisterID> func = generator.newTemporary();
439 CallArguments callArguments(generator, m_args);
440 int identifierStart = divot() - startOffset();
442 generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
443 generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident);
444 return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
447 // ------------------------------ FunctionCallBracketNode ----------------------------------
449 RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
451 RefPtr<RegisterID> base = generator.emitNode(m_base);
452 RegisterID* property = generator.emitNode(m_subscript);
453 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
454 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
455 CallArguments callArguments(generator, m_args);
456 generator.emitMove(callArguments.thisRegister(), base.get());
457 return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset());
460 // ------------------------------ FunctionCallDotNode ----------------------------------
462 RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
464 RefPtr<RegisterID> function = generator.tempDestination(dst);
465 CallArguments callArguments(generator, m_args);
466 generator.emitNode(callArguments.thisRegister(), m_base);
467 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
468 generator.emitMethodCheck();
469 generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
470 return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset());
473 RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
475 RefPtr<Label> realCall = generator.newLabel();
476 RefPtr<Label> end = generator.newLabel();
477 RefPtr<RegisterID> base = generator.emitNode(m_base);
478 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
479 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
480 RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
481 generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
483 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
484 ArgumentListNode* oldList = m_args->m_listNode;
485 m_args->m_listNode = m_args->m_listNode->m_next;
487 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
488 CallArguments callArguments(generator, m_args);
489 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
490 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
491 generator.emitJump(end.get());
493 m_args->m_listNode = oldList;
495 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
496 CallArguments callArguments(generator, m_args);
497 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
498 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
499 generator.emitJump(end.get());
502 generator.emitLabel(realCall.get());
504 CallArguments callArguments(generator, m_args);
505 generator.emitMove(callArguments.thisRegister(), base.get());
506 generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
508 generator.emitLabel(end.get());
509 return finalDestinationOrIgnored.get();
512 static bool areTrivialApplyArguments(ArgumentsNode* args)
514 return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
515 || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray());
518 RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
520 // A few simple cases can be trivially handled as ordinary function calls.
521 // function.apply(), function.apply(arg) -> identical to function.call
522 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
523 bool mayBeCall = areTrivialApplyArguments(m_args);
525 RefPtr<Label> realCall = generator.newLabel();
526 RefPtr<Label> end = generator.newLabel();
527 RefPtr<RegisterID> base = generator.emitNode(m_base);
528 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
529 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
530 RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
531 generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
534 if (m_args->m_listNode && m_args->m_listNode->m_expr) {
535 ArgumentListNode* oldList = m_args->m_listNode;
536 if (m_args->m_listNode->m_next) {
537 ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
538 ASSERT(!m_args->m_listNode->m_next->m_next);
539 m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData(), 0);
540 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
541 CallArguments callArguments(generator, m_args);
542 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
543 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
545 m_args->m_listNode = m_args->m_listNode->m_next;
546 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
547 CallArguments callArguments(generator, m_args);
548 generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
549 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
551 m_args->m_listNode = oldList;
553 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
554 CallArguments callArguments(generator, m_args);
555 generator.emitLoad(callArguments.thisRegister(), jsUndefined());
556 generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
559 ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
560 RefPtr<RegisterID> profileHookRegister;
561 if (generator.shouldEmitProfileHooks())
562 profileHookRegister = generator.newTemporary();
563 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
564 RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
565 RefPtr<RegisterID> argsRegister;
566 ArgumentListNode* args = m_args->m_listNode->m_next;
567 if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()))
568 argsRegister = generator.uncheckedRegisterForArguments();
570 argsRegister = generator.emitNode(args->m_expr);
572 // Function.prototype.apply ignores extra arguments, but we still
573 // need to evaluate them for side effects.
574 while ((args = args->m_next))
575 generator.emitNode(args->m_expr);
577 generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), startOffset(), endOffset());
579 generator.emitJump(end.get());
581 generator.emitLabel(realCall.get());
583 CallArguments callArguments(generator, m_args);
584 generator.emitMove(callArguments.thisRegister(), base.get());
585 generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
587 generator.emitLabel(end.get());
588 return finalDestinationOrIgnored.get();
591 // ------------------------------ PostfixResolveNode ----------------------------------
593 static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
595 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
598 static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
601 return generator.emitToJSNumber(dst, srcDst);
602 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
605 RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
607 ResolveResult resolveResult = generator.resolve(m_ident);
609 if (RegisterID* local = resolveResult.local()) {
610 if (resolveResult.isReadOnly()) {
611 if (dst == generator.ignoredResult())
613 return generator.emitToJSNumber(generator.finalDestination(dst), local);
615 if (dst == generator.ignoredResult())
616 return emitPreIncOrDec(generator, local, m_operator);
617 return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator);
620 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
621 RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult);
622 RegisterID* oldValue;
623 if (dst == generator.ignoredResult()) {
625 emitPreIncOrDec(generator, value.get(), m_operator);
627 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
629 generator.emitPutStaticVar(resolveResult, value.get());
633 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
634 RefPtr<RegisterID> value = generator.newTemporary();
635 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), resolveResult, m_ident);
636 RegisterID* oldValue;
637 if (dst == generator.ignoredResult()) {
639 emitPreIncOrDec(generator, value.get(), m_operator);
641 oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
643 generator.emitPutById(base.get(), m_ident, value.get());
647 // ------------------------------ PostfixBracketNode ----------------------------------
649 RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
651 RefPtr<RegisterID> base = generator.emitNode(m_base);
652 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
654 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
655 RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get());
656 RegisterID* oldValue;
657 if (dst == generator.ignoredResult()) {
659 if (m_operator == OpPlusPlus)
660 generator.emitPreInc(value.get());
662 generator.emitPreDec(value.get());
664 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
666 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
667 generator.emitPutByVal(base.get(), property.get(), value.get());
671 // ------------------------------ PostfixDotNode ----------------------------------
673 RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
675 RefPtr<RegisterID> base = generator.emitNode(m_base);
677 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
678 RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
679 RegisterID* oldValue;
680 if (dst == generator.ignoredResult()) {
682 if (m_operator == OpPlusPlus)
683 generator.emitPreInc(value.get());
685 generator.emitPreDec(value.get());
687 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get());
689 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
690 generator.emitPutById(base.get(), m_ident, value.get());
694 // ------------------------------ PostfixErrorNode -----------------------------------
696 RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
698 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
699 ? "Postfix ++ operator applied to value that is not a reference."
700 : "Postfix -- operator applied to value that is not a reference.");
703 // ------------------------------ DeleteResolveNode -----------------------------------
705 RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
707 ResolveResult resolveResult = generator.resolve(m_ident);
708 if (resolveResult.isRegister())
709 return generator.emitLoad(generator.finalDestination(dst), false);
711 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
712 RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident);
713 return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
716 // ------------------------------ DeleteBracketNode -----------------------------------
718 RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
720 RefPtr<RegisterID> r0 = generator.emitNode(m_base);
721 RegisterID* r1 = generator.emitNode(m_subscript);
723 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
724 return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1);
727 // ------------------------------ DeleteDotNode -----------------------------------
729 RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
731 RegisterID* r0 = generator.emitNode(m_base);
733 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
734 return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident);
737 // ------------------------------ DeleteValueNode -----------------------------------
739 RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
741 generator.emitNode(generator.ignoredResult(), m_expr);
743 // delete on a non-location expression ignores the value and returns true
744 return generator.emitLoad(generator.finalDestination(dst), true);
747 // ------------------------------ VoidNode -------------------------------------
749 RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
751 if (dst == generator.ignoredResult()) {
752 generator.emitNode(generator.ignoredResult(), m_expr);
755 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
756 return generator.emitLoad(dst, jsUndefined());
759 // ------------------------------ TypeOfValueNode -----------------------------------
761 RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
763 ResolveResult resolveResult = generator.resolve(m_ident);
764 if (RegisterID* local = resolveResult.local()) {
765 if (dst == generator.ignoredResult())
767 return generator.emitTypeOf(generator.finalDestination(dst), local);
770 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident);
771 generator.emitGetById(scratch.get(), scratch.get(), m_ident);
772 if (dst == generator.ignoredResult())
774 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get());
777 // ------------------------------ TypeOfValueNode -----------------------------------
779 RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
781 if (dst == generator.ignoredResult()) {
782 generator.emitNode(generator.ignoredResult(), m_expr);
785 RefPtr<RegisterID> src = generator.emitNode(m_expr);
786 return generator.emitTypeOf(generator.finalDestination(dst), src.get());
789 // ------------------------------ PrefixResolveNode ----------------------------------
791 RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
793 ResolveResult resolveResult = generator.resolve(m_ident);
794 if (RegisterID* local = resolveResult.local()) {
795 if (resolveResult.isReadOnly()) {
796 if (dst == generator.ignoredResult())
798 RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
799 return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
801 emitPreIncOrDec(generator, local, m_operator);
802 return generator.moveToDestinationIfNeeded(dst, local);
805 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
806 RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
807 emitPreIncOrDec(generator, propDst.get(), m_operator);
808 generator.emitPutStaticVar(resolveResult, propDst.get());
809 return generator.moveToDestinationIfNeeded(dst, propDst.get());
812 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
813 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
814 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), resolveResult, m_ident);
815 emitPreIncOrDec(generator, propDst.get(), m_operator);
816 generator.emitPutById(base.get(), m_ident, propDst.get());
817 return generator.moveToDestinationIfNeeded(dst, propDst.get());
820 // ------------------------------ PrefixBracketNode ----------------------------------
822 RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
824 RefPtr<RegisterID> base = generator.emitNode(m_base);
825 RefPtr<RegisterID> property = generator.emitNode(m_subscript);
826 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
828 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
829 RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get());
830 if (m_operator == OpPlusPlus)
831 generator.emitPreInc(value);
833 generator.emitPreDec(value);
834 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
835 generator.emitPutByVal(base.get(), property.get(), value);
836 return generator.moveToDestinationIfNeeded(dst, propDst.get());
839 // ------------------------------ PrefixDotNode ----------------------------------
841 RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
843 RefPtr<RegisterID> base = generator.emitNode(m_base);
844 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
846 generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset);
847 RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident);
848 if (m_operator == OpPlusPlus)
849 generator.emitPreInc(value);
851 generator.emitPreDec(value);
852 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
853 generator.emitPutById(base.get(), m_ident, value);
854 return generator.moveToDestinationIfNeeded(dst, propDst.get());
857 // ------------------------------ PrefixErrorNode -----------------------------------
859 RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
861 return emitThrowReferenceError(generator, m_operator == OpPlusPlus
862 ? "Prefix ++ operator applied to value that is not a reference."
863 : "Prefix -- operator applied to value that is not a reference.");
866 // ------------------------------ Unary Operation Nodes -----------------------------------
868 RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
870 RegisterID* src = generator.emitNode(m_expr);
871 return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src);
874 // ------------------------------ BitwiseNotNode -----------------------------------
876 RegisterID* BitwiseNotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
878 RefPtr<RegisterID> src2 = generator.emitLoad(generator.newTemporary(), jsNumber(-1));
879 RegisterID* src1 = generator.emitNode(m_expr);
880 return generator.emitBinaryOp(op_bitxor, generator.finalDestination(dst, src1), src1, src2.get(), OperandTypes(m_expr->resultDescriptor(), ResultType::numberTypeIsInt32()));
883 // ------------------------------ LogicalNotNode -----------------------------------
885 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
887 ASSERT(expr()->hasConditionContextCodegen());
889 // reverse the true and false targets
890 generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue);
894 // ------------------------------ Binary Operation Nodes -----------------------------------
896 // BinaryOpNode::emitStrcat:
898 // This node generates an op_strcat operation. This opcode can handle concatenation of three or
899 // more values, where we can determine a set of separate op_add operations would be operating on
902 // This function expects to be operating on a graph of AST nodes looking something like this:
912 // The assignment operation is optional, if it exists the register holding the value on the
913 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
915 // The method should be called on the node at the root of the tree of regular binary add
916 // operations (marked in the diagram with a double set of parentheses). This node must
917 // be performing a string concatenation (determined by statically detecting that at least
918 // one child must be a string).
920 // Since the minimum number of values being concatenated together is expected to be 3, if
921 // a lhs to a concatenating assignment is not provided then the root add should have at
922 // least one left child that is also an add that can be determined to be operating on strings.
924 RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe)
927 ASSERT(resultDescriptor().definitelyIsString());
929 // Create a list of expressions for all the adds in the tree of nodes we can convert into
930 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
931 // added first, and the leftmost child is never added, so the vector produced for the
932 // example above will be [ c, b ].
933 Vector<ExpressionNode*, 16> reverseExpressionList;
934 reverseExpressionList.append(m_expr2);
936 // Examine the left child of the add. So long as this is a string add, add its right-child
937 // to the list, and keep processing along the left fork.
938 ExpressionNode* leftMostAddChild = m_expr1;
939 while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) {
940 reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2);
941 leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1;
944 Vector<RefPtr<RegisterID>, 16> temporaryRegisters;
946 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
947 // We could possibly avoid this (the lhs is converted last anyway, we could let the
948 // op_strcat node handle its conversion if required).
950 temporaryRegisters.append(generator.newTemporary());
952 // Emit code for the leftmost node ((a) in the example).
953 temporaryRegisters.append(generator.newTemporary());
954 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
955 generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild);
957 // Note on ordering of conversions:
959 // We maintain the same ordering of conversions as we would see if the concatenations
960 // was performed as a sequence of adds (otherwise this optimization could change
961 // behaviour should an object have been provided a valueOf or toString method).
963 // Considering the above example, the sequnce of execution is:
964 // * evaluate operand (a)
965 // * evaluate operand (b)
966 // * convert (a) to primitive <- (this would be triggered by the first add)
967 // * convert (b) to primitive <- (ditto)
968 // * evaluate operand (c)
969 // * convert (c) to primitive <- (this would be triggered by the second add)
970 // And optionally, if there is an assignment:
971 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
973 // As such we do not plant an op to convert the leftmost child now. Instead, use
974 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
975 // once the second node has been generated. However, if the leftmost child is an
976 // immediate we can trivially determine that no conversion will be required.
977 // If this is the case
978 if (leftMostAddChild->isString())
979 leftMostAddChildTempRegister = 0;
981 while (reverseExpressionList.size()) {
982 ExpressionNode* node = reverseExpressionList.last();
983 reverseExpressionList.removeLast();
985 // Emit the code for the current node.
986 temporaryRegisters.append(generator.newTemporary());
987 generator.emitNode(temporaryRegisters.last().get(), node);
989 // On the first iteration of this loop, when we first reach this point we have just
990 // generated the second node, which means it is time to convert the leftmost operand.
991 if (leftMostAddChildTempRegister) {
992 generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister);
993 leftMostAddChildTempRegister = 0; // Only do this once.
995 // Plant a conversion for this node, if necessary.
996 if (!node->isString())
997 generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get());
999 ASSERT(temporaryRegisters.size() >= 3);
1001 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1002 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1003 if (emitExpressionInfoForMe)
1004 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
1006 // If there is an assignment convert the lhs now. This will also copy lhs to
1007 // the temporary register we allocated for it.
1009 generator.emitToPrimitive(temporaryRegisters[0].get(), lhs);
1011 return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size());
1014 RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1016 OpcodeID opcodeID = this->opcodeID();
1018 if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString())
1019 return emitStrcat(generator, dst);
1021 if (opcodeID == op_neq) {
1022 if (m_expr1->isNull() || m_expr2->isNull()) {
1023 RefPtr<RegisterID> src = generator.tempDestination(dst);
1024 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1025 return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get());
1029 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1030 RegisterID* src2 = generator.emitNode(m_expr2);
1031 return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1034 RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1036 if (m_expr1->isNull() || m_expr2->isNull()) {
1037 RefPtr<RegisterID> src = generator.tempDestination(dst);
1038 generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1);
1039 return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get());
1042 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1043 RegisterID* src2 = generator.emitNode(m_expr2);
1044 return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1047 RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1049 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1050 RegisterID* src2 = generator.emitNode(m_expr2);
1051 return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2);
1054 RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1056 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1057 RegisterID* src2 = generator.emitNode(m_expr2);
1058 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1059 return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
1062 RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1064 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
1065 RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
1067 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1068 generator.emitCheckHasInstance(src2.get());
1070 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1071 RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
1073 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1074 return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype);
1077 // ------------------------------ LogicalOpNode ----------------------------
1079 RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1081 RefPtr<RegisterID> temp = generator.tempDestination(dst);
1082 RefPtr<Label> target = generator.newLabel();
1084 generator.emitNode(temp.get(), m_expr1);
1085 if (m_operator == OpLogicalAnd)
1086 generator.emitJumpIfFalse(temp.get(), target.get());
1088 generator.emitJumpIfTrue(temp.get(), target.get());
1089 generator.emitNode(temp.get(), m_expr2);
1090 generator.emitLabel(target.get());
1092 return generator.moveToDestinationIfNeeded(dst, temp.get());
1095 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
1097 if (m_expr1->hasConditionContextCodegen()) {
1098 RefPtr<Label> afterExpr1 = generator.newLabel();
1099 if (m_operator == OpLogicalAnd)
1100 generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, true);
1102 generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), false);
1103 generator.emitLabel(afterExpr1.get());
1105 RegisterID* temp = generator.emitNode(m_expr1);
1106 if (m_operator == OpLogicalAnd)
1107 generator.emitJumpIfFalse(temp, falseTarget);
1109 generator.emitJumpIfTrue(temp, trueTarget);
1112 if (m_expr2->hasConditionContextCodegen())
1113 generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMeansTrue);
1115 RegisterID* temp = generator.emitNode(m_expr2);
1116 if (fallThroughMeansTrue)
1117 generator.emitJumpIfFalse(temp, falseTarget);
1119 generator.emitJumpIfTrue(temp, trueTarget);
1123 // ------------------------------ ConditionalNode ------------------------------
1125 RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1127 RefPtr<RegisterID> newDst = generator.finalDestination(dst);
1128 RefPtr<Label> beforeElse = generator.newLabel();
1129 RefPtr<Label> afterElse = generator.newLabel();
1131 if (m_logical->hasConditionContextCodegen()) {
1132 RefPtr<Label> beforeThen = generator.newLabel();
1133 generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), true);
1134 generator.emitLabel(beforeThen.get());
1136 RegisterID* cond = generator.emitNode(m_logical);
1137 generator.emitJumpIfFalse(cond, beforeElse.get());
1140 generator.emitNode(newDst.get(), m_expr1);
1141 generator.emitJump(afterElse.get());
1143 generator.emitLabel(beforeElse.get());
1144 generator.emitNode(newDst.get(), m_expr2);
1146 generator.emitLabel(afterElse.get());
1148 return newDst.get();
1151 // ------------------------------ ReadModifyResolveNode -----------------------------------
1153 // FIXME: should this be moved to be a method on BytecodeGenerator?
1154 static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0)
1165 if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString())
1166 return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe);
1173 opcodeID = op_lshift;
1176 opcodeID = op_rshift;
1179 opcodeID = op_urshift;
1182 opcodeID = op_bitand;
1185 opcodeID = op_bitxor;
1188 opcodeID = op_bitor;
1194 ASSERT_NOT_REACHED();
1198 RegisterID* src2 = generator.emitNode(m_right);
1200 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1201 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1202 if (emitExpressionInfoForMe)
1203 generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset());
1205 return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1208 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1210 ResolveResult resolveResult = generator.resolve(m_ident);
1212 if (RegisterID *local = resolveResult.local()) {
1213 if (resolveResult.isReadOnly())
1214 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1216 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
1217 RefPtr<RegisterID> result = generator.newTemporary();
1218 generator.emitMove(result.get(), local);
1219 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1220 generator.emitMove(local, result.get());
1221 return generator.moveToDestinationIfNeeded(dst, result.get());
1224 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1225 return generator.moveToDestinationIfNeeded(dst, result);
1228 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
1229 RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
1230 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1231 generator.emitPutStaticVar(resolveResult, result);
1235 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
1236 generator.emitExpressionInfo(divot() - startOffset() + m_ident.length(), m_ident.length(), 0);
1237 RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), resolveResult, m_ident);
1238 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
1239 return generator.emitPutById(base.get(), m_ident, result);
1242 // ------------------------------ AssignResolveNode -----------------------------------
1244 RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1246 ResolveResult resolveResult = generator.resolve(m_ident);
1248 if (RegisterID *local = resolveResult.local()) {
1249 if (resolveResult.isReadOnly())
1250 return generator.emitNode(dst, m_right);
1251 RegisterID* result = generator.emitNode(local, m_right);
1252 return generator.moveToDestinationIfNeeded(dst, result);
1255 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
1256 if (dst == generator.ignoredResult())
1258 RegisterID* value = generator.emitNode(dst, m_right);
1259 generator.emitPutStaticVar(resolveResult, value);
1263 RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, m_ident);
1264 if (dst == generator.ignoredResult())
1266 RegisterID* value = generator.emitNode(dst, m_right);
1267 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1268 return generator.emitPutById(base.get(), m_ident, value);
1271 // ------------------------------ AssignDotNode -----------------------------------
1273 RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1275 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1276 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1277 RegisterID* result = generator.emitNode(value.get(), m_right);
1278 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1279 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1280 generator.emitPutById(base.get(), m_ident, forwardResult);
1281 return generator.moveToDestinationIfNeeded(dst, forwardResult);
1284 // ------------------------------ ReadModifyDotNode -----------------------------------
1286 RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1288 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator));
1290 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1291 RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
1292 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1294 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1295 return generator.emitPutById(base.get(), m_ident, updatedValue);
1298 // ------------------------------ AssignErrorNode -----------------------------------
1300 RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1302 return emitThrowReferenceError(generator, "Left side of assignment is not a reference.");
1305 // ------------------------------ AssignBracketNode -----------------------------------
1307 RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1309 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1310 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1311 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1312 RegisterID* result = generator.emitNode(value.get(), m_right);
1314 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1315 RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
1316 generator.emitPutByVal(base.get(), property.get(), forwardResult);
1317 return generator.moveToDestinationIfNeeded(dst, forwardResult);
1320 // ------------------------------ ReadModifyBracketNode -----------------------------------
1322 RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1324 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator));
1325 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator));
1327 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
1328 RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
1329 RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1331 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1332 generator.emitPutByVal(base.get(), property.get(), updatedValue);
1334 return updatedValue;
1337 // ------------------------------ CommaNode ------------------------------------
1339 RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1341 ASSERT(m_expressions.size() > 1);
1342 for (size_t i = 0; i < m_expressions.size() - 1; i++)
1343 generator.emitNode(generator.ignoredResult(), m_expressions[i]);
1344 return generator.emitNode(dst, m_expressions.last());
1347 // ------------------------------ ConstDeclNode ------------------------------------
1349 RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
1351 ResolveResult resolveResult = generator.resolveConstDecl(m_ident);
1353 // FIXME: This code does not match the behavior of const in Firefox.
1354 if (RegisterID* local = resolveResult.local()) {
1358 return generator.emitNode(local, m_init);
1361 RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
1363 if (resolveResult.isStatic())
1364 return generator.emitPutStaticVar(resolveResult, value.get());
1366 if (generator.codeType() != EvalCode)
1369 // FIXME: While this code should only be hit in an eval block, it will assign
1370 // to the wrong base if m_ident exists in an intervening with scope.
1371 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), resolveResult, m_ident);
1372 return generator.emitPutById(base.get(), m_ident, value.get());
1375 RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1377 RegisterID* result = 0;
1378 for (ConstDeclNode* n = this; n; n = n->m_next)
1379 result = n->emitCodeSingle(generator);
1384 // ------------------------------ ConstStatementNode -----------------------------
1386 RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1388 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1389 return generator.emitNode(m_next);
1392 // ------------------------------ SourceElements -------------------------------
1395 inline StatementNode* SourceElements::lastStatement() const
1397 size_t size = m_statements.size();
1398 return size ? m_statements[size - 1] : 0;
1401 inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1403 size_t size = m_statements.size();
1404 for (size_t i = 0; i < size; ++i)
1405 generator.emitNode(dst, m_statements[i]);
1408 // ------------------------------ BlockNode ------------------------------------
1410 inline StatementNode* BlockNode::lastStatement() const
1412 return m_statements ? m_statements->lastStatement() : 0;
1415 inline StatementNode* BlockNode::singleStatement() const
1417 return m_statements ? m_statements->singleStatement() : 0;
1420 RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1423 m_statements->emitBytecode(generator, dst);
1427 // ------------------------------ EmptyStatementNode ---------------------------
1429 RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1431 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1435 // ------------------------------ DebuggerStatementNode ---------------------------
1437 RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1439 generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine());
1443 // ------------------------------ ExprStatementNode ----------------------------
1445 RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1448 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1449 return generator.emitNode(dst, m_expr);
1452 // ------------------------------ VarStatementNode ----------------------------
1454 RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1457 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1458 return generator.emitNode(m_expr);
1461 // ------------------------------ IfNode ---------------------------------------
1463 RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1465 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1467 RefPtr<Label> afterThen = generator.newLabel();
1469 if (m_condition->hasConditionContextCodegen()) {
1470 RefPtr<Label> beforeThen = generator.newLabel();
1471 generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), true);
1472 generator.emitLabel(beforeThen.get());
1474 RegisterID* cond = generator.emitNode(m_condition);
1475 generator.emitJumpIfFalse(cond, afterThen.get());
1478 generator.emitNode(dst, m_ifBlock);
1479 generator.emitLabel(afterThen.get());
1481 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1485 // ------------------------------ IfElseNode ---------------------------------------
1487 RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1489 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1491 RefPtr<Label> beforeElse = generator.newLabel();
1492 RefPtr<Label> afterElse = generator.newLabel();
1494 if (m_condition->hasConditionContextCodegen()) {
1495 RefPtr<Label> beforeThen = generator.newLabel();
1496 generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), true);
1497 generator.emitLabel(beforeThen.get());
1499 RegisterID* cond = generator.emitNode(m_condition);
1500 generator.emitJumpIfFalse(cond, beforeElse.get());
1503 generator.emitNode(dst, m_ifBlock);
1504 generator.emitJump(afterElse.get());
1506 generator.emitLabel(beforeElse.get());
1508 generator.emitNode(dst, m_elseBlock);
1510 generator.emitLabel(afterElse.get());
1512 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1516 // ------------------------------ DoWhileNode ----------------------------------
1518 RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1520 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1522 RefPtr<Label> topOfLoop = generator.newLabel();
1523 generator.emitLabel(topOfLoop.get());
1524 generator.emitLoopHint();
1525 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1527 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
1529 generator.emitLabel(scope->continueTarget());
1530 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1531 if (m_expr->hasConditionContextCodegen())
1532 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
1534 RegisterID* cond = generator.emitNode(m_expr);
1535 generator.emitJumpIfTrue(cond, topOfLoop.get());
1538 generator.emitLabel(scope->breakTarget());
1539 return result.get();
1542 // ------------------------------ WhileNode ------------------------------------
1544 RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1546 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1547 RefPtr<Label> topOfLoop = generator.newLabel();
1549 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1550 if (m_expr->hasConditionContextCodegen())
1551 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), true);
1553 RegisterID* cond = generator.emitNode(m_expr);
1554 generator.emitJumpIfFalse(cond, scope->breakTarget());
1557 generator.emitLabel(topOfLoop.get());
1558 generator.emitLoopHint();
1560 generator.emitNode(dst, m_statement);
1562 generator.emitLabel(scope->continueTarget());
1563 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1565 if (m_expr->hasConditionContextCodegen())
1566 generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false);
1568 RegisterID* cond = generator.emitNode(m_expr);
1569 generator.emitJumpIfTrue(cond, topOfLoop.get());
1572 generator.emitLabel(scope->breakTarget());
1574 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1578 // ------------------------------ ForNode --------------------------------------
1580 RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1582 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1584 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1587 generator.emitNode(generator.ignoredResult(), m_expr1);
1589 RefPtr<Label> topOfLoop = generator.newLabel();
1591 if (m_expr2->hasConditionContextCodegen())
1592 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), true);
1594 RegisterID* cond = generator.emitNode(m_expr2);
1595 generator.emitJumpIfFalse(cond, scope->breakTarget());
1599 generator.emitLabel(topOfLoop.get());
1600 generator.emitLoopHint();
1602 RefPtr<RegisterID> result = generator.emitNode(dst, m_statement);
1604 generator.emitLabel(scope->continueTarget());
1605 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1607 generator.emitNode(generator.ignoredResult(), m_expr3);
1610 if (m_expr2->hasConditionContextCodegen())
1611 generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), false);
1613 RegisterID* cond = generator.emitNode(m_expr2);
1614 generator.emitJumpIfTrue(cond, topOfLoop.get());
1617 generator.emitJump(topOfLoop.get());
1619 generator.emitLabel(scope->breakTarget());
1620 return result.get();
1623 // ------------------------------ ForInNode ------------------------------------
1625 RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1627 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1629 if (!m_lexpr->isLocation())
1630 return emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
1632 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1635 generator.emitNode(generator.ignoredResult(), m_init);
1637 RefPtr<RegisterID> base = generator.newTemporary();
1638 generator.emitNode(base.get(), m_expr);
1639 RefPtr<RegisterID> i = generator.newTemporary();
1640 RefPtr<RegisterID> size = generator.newTemporary();
1641 RefPtr<RegisterID> expectedSubscript;
1642 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
1643 generator.emitJump(scope->continueTarget());
1645 RefPtr<Label> loopStart = generator.newLabel();
1646 generator.emitLabel(loopStart.get());
1647 generator.emitLoopHint();
1649 RegisterID* propertyName;
1650 bool optimizedForinAccess = false;
1651 if (m_lexpr->isResolveNode()) {
1652 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1653 ResolveResult resolveResult = generator.resolve(ident);
1654 propertyName = resolveResult.local();
1655 if (!propertyName) {
1656 propertyName = generator.newTemporary();
1657 RefPtr<RegisterID> protect = propertyName;
1658 RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, ident);
1660 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1661 generator.emitPutById(base, ident, propertyName);
1663 expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
1664 generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
1665 optimizedForinAccess = true;
1667 } else if (m_lexpr->isDotAccessorNode()) {
1668 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1669 const Identifier& ident = assignNode->identifier();
1670 propertyName = generator.newTemporary();
1671 RefPtr<RegisterID> protect = propertyName;
1672 RegisterID* base = generator.emitNode(assignNode->base());
1674 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1675 generator.emitPutById(base, ident, propertyName);
1677 ASSERT(m_lexpr->isBracketAccessorNode());
1678 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1679 propertyName = generator.newTemporary();
1680 RefPtr<RegisterID> protect = propertyName;
1681 RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
1682 RegisterID* subscript = generator.emitNode(assignNode->subscript());
1684 generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset());
1685 generator.emitPutByVal(base.get(), subscript, propertyName);
1688 generator.emitNode(dst, m_statement);
1690 if (optimizedForinAccess)
1691 generator.popOptimisedForIn();
1693 generator.emitLabel(scope->continueTarget());
1694 generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
1695 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1696 generator.emitLabel(scope->breakTarget());
1700 // ------------------------------ ContinueNode ---------------------------------
1703 RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1705 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1707 LabelScope* scope = generator.continueTarget(m_ident);
1710 generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
1714 // ------------------------------ BreakNode ------------------------------------
1717 RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1719 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1721 LabelScope* scope = generator.breakTarget(m_ident);
1724 generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
1728 // ------------------------------ ReturnNode -----------------------------------
1730 RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1732 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1733 ASSERT(generator.codeType() == FunctionCode);
1735 if (dst == generator.ignoredResult())
1737 RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
1738 RefPtr<RegisterID> returnRegister;
1739 if (generator.scopeDepth()) {
1740 RefPtr<Label> l0 = generator.newLabel();
1741 if (generator.hasFinaliser()) {
1742 returnRegister = generator.emitMove(generator.newTemporary(), r0);
1743 r0 = returnRegister.get();
1745 generator.emitJumpScopes(l0.get(), 0);
1746 generator.emitLabel(l0.get());
1748 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
1749 return generator.emitReturn(r0);
1752 // ------------------------------ WithNode -------------------------------------
1754 RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1756 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1758 RefPtr<RegisterID> scope = generator.newTemporary();
1759 generator.emitNode(scope.get(), m_expr); // scope must be protected until popped
1760 generator.emitExpressionInfo(m_divot, m_expressionLength, 0);
1761 generator.emitPushScope(scope.get());
1762 RegisterID* result = generator.emitNode(dst, m_statement);
1763 generator.emitPopScope();
1767 // ------------------------------ CaseClauseNode --------------------------------
1769 inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1772 m_statements->emitBytecode(generator, dst);
1775 // ------------------------------ CaseBlockNode --------------------------------
1784 static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
1786 for (; list; list = list->getNext()) {
1787 ExpressionNode* clauseExpression = list->getClause()->expr();
1788 literalVector.append(clauseExpression);
1789 if (clauseExpression->isNumber()) {
1790 double value = static_cast<NumberNode*>(clauseExpression)->value();
1791 int32_t intVal = static_cast<int32_t>(value);
1792 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
1793 typeForTable = SwitchNeither;
1796 if (intVal < min_num)
1798 if (intVal > max_num)
1800 typeForTable = SwitchNumber;
1803 if (clauseExpression->isString()) {
1804 if (typeForTable & ~SwitchString) {
1805 typeForTable = SwitchNeither;
1808 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
1809 if (singleCharacterSwitch &= value.length() == 1) {
1810 int32_t intVal = value[0];
1811 if (intVal < min_num)
1813 if (intVal > max_num)
1816 typeForTable = SwitchString;
1819 typeForTable = SwitchNeither;
1824 SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
1826 SwitchKind typeForTable = SwitchUnset;
1827 bool singleCharacterSwitch = true;
1829 processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1830 processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1832 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
1833 return SwitchInfo::SwitchNone;
1835 if (typeForTable == SwitchNumber) {
1836 int32_t range = max_num - min_num;
1837 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1838 return SwitchInfo::SwitchImmediate;
1839 return SwitchInfo::SwitchNone;
1842 ASSERT(typeForTable == SwitchString);
1844 if (singleCharacterSwitch) {
1845 int32_t range = max_num - min_num;
1846 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1847 return SwitchInfo::SwitchCharacter;
1850 return SwitchInfo::SwitchString;
1853 RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1855 RefPtr<Label> defaultLabel;
1856 Vector<RefPtr<Label>, 8> labelVector;
1857 Vector<ExpressionNode*, 8> literalVector;
1858 int32_t min_num = std::numeric_limits<int32_t>::max();
1859 int32_t max_num = std::numeric_limits<int32_t>::min();
1860 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
1862 if (switchType != SwitchInfo::SwitchNone) {
1863 // Prepare the various labels
1864 for (uint32_t i = 0; i < literalVector.size(); i++)
1865 labelVector.append(generator.newLabel());
1866 defaultLabel = generator.newLabel();
1867 generator.beginSwitch(switchExpression, switchType);
1870 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1871 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1872 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1873 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1874 labelVector.append(generator.newLabel());
1875 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1878 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1879 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1880 generator.emitNode(clauseVal.get(), list->getClause()->expr());
1881 generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes());
1882 labelVector.append(generator.newLabel());
1883 generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get());
1885 defaultLabel = generator.newLabel();
1886 generator.emitJump(defaultLabel.get());
1889 RegisterID* result = 0;
1892 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1893 generator.emitLabel(labelVector[i++].get());
1894 list->getClause()->emitBytecode(generator, dst);
1897 if (m_defaultClause) {
1898 generator.emitLabel(defaultLabel.get());
1899 m_defaultClause->emitBytecode(generator, dst);
1902 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1903 generator.emitLabel(labelVector[i++].get());
1904 list->getClause()->emitBytecode(generator, dst);
1906 if (!m_defaultClause)
1907 generator.emitLabel(defaultLabel.get());
1909 ASSERT(i == labelVector.size());
1910 if (switchType != SwitchInfo::SwitchNone) {
1911 ASSERT(labelVector.size() == literalVector.size());
1912 generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num);
1917 // ------------------------------ SwitchNode -----------------------------------
1919 RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1921 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1923 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
1925 RefPtr<RegisterID> r0 = generator.emitNode(m_expr);
1926 RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst);
1928 generator.emitLabel(scope->breakTarget());
1932 // ------------------------------ LabelNode ------------------------------------
1934 RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1936 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1938 ASSERT(!generator.breakTarget(m_name));
1940 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
1941 RegisterID* r0 = generator.emitNode(dst, m_statement);
1943 generator.emitLabel(scope->breakTarget());
1947 // ------------------------------ ThrowNode ------------------------------------
1949 RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1951 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1953 if (dst == generator.ignoredResult())
1955 RefPtr<RegisterID> expr = generator.emitNode(m_expr);
1956 generator.emitExpressionInfo(divot(), startOffset(), endOffset());
1957 generator.emitThrow(expr.get());
1961 // ------------------------------ TryNode --------------------------------------
1963 RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1965 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1966 // optimizer knows they may be jumped to from anywhere.
1968 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1970 RefPtr<Label> tryStartLabel = generator.newLabel();
1972 generator.pushFinallyContext(m_finallyBlock);
1974 generator.emitLabel(tryStartLabel.get());
1975 generator.emitNode(dst, m_tryBlock);
1978 RefPtr<Label> catchEndLabel = generator.newLabel();
1980 // Normal path: jump over the catch block.
1981 generator.emitJump(catchEndLabel.get());
1983 // Uncaught exception path: the catch block.
1984 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
1985 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
1986 generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get());
1987 generator.emitNode(dst, m_catchBlock);
1988 generator.emitPopScope();
1989 generator.emitLabel(catchEndLabel.get());
1992 if (m_finallyBlock) {
1993 generator.popFinallyContext();
1995 RefPtr<Label> finallyEndLabel = generator.newLabel();
1997 // Normal path: run the finally code, and jump to the end.
1998 generator.emitNode(dst, m_finallyBlock);
1999 generator.emitJump(finallyEndLabel.get());
2001 // Uncaught exception path: invoke the finally block, then re-throw the exception.
2002 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
2003 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
2004 generator.emitNode(dst, m_finallyBlock);
2005 generator.emitThrow(tempExceptionRegister.get());
2007 generator.emitLabel(finallyEndLabel.get());
2013 // ------------------------------ ScopeNode -----------------------------
2015 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
2018 m_statements->emitBytecode(generator, dst);
2021 // ------------------------------ ProgramNode -----------------------------
2023 RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2025 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2027 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2028 generator.emitLoad(dstRegister.get(), jsUndefined());
2029 emitStatementsBytecode(generator, dstRegister.get());
2031 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2032 generator.emitEnd(dstRegister.get());
2036 // ------------------------------ EvalNode -----------------------------
2038 RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2040 generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine());
2042 RefPtr<RegisterID> dstRegister = generator.newTemporary();
2043 generator.emitLoad(dstRegister.get(), jsUndefined());
2044 emitStatementsBytecode(generator, dstRegister.get());
2046 generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine());
2047 generator.emitEnd(dstRegister.get());
2051 // ------------------------------ FunctionBodyNode -----------------------------
2053 RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
2055 generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
2056 emitStatementsBytecode(generator, generator.ignoredResult());
2058 StatementNode* singleStatement = this->singleStatement();
2059 ReturnNode* returnNode = 0;
2061 // Check for a return statement at the end of a function composed of a single block.
2062 if (singleStatement && singleStatement->isBlock()) {
2063 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
2064 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
2065 returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
2068 // If there is no return we must automatically insert one.
2070 RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
2071 generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
2072 generator.emitReturn(r0);
2076 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
2077 if (static_cast<BlockNode*>(singleStatement)->singleStatement()) {
2078 ExpressionNode* returnValueExpression = returnNode->value();
2079 if (returnValueExpression && returnValueExpression->isSubtract()) {
2080 ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
2081 ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
2082 if (lhsExpression->isResolveNode()
2083 && rhsExpression->isResolveNode()
2084 && generator.isArgumentNumber(static_cast<ResolveNode*>(lhsExpression)->identifier(), 0)
2085 && generator.isArgumentNumber(static_cast<ResolveNode*>(rhsExpression)->identifier(), 1)) {
2087 generator.setIsNumericCompareFunction(true);
2095 // ------------------------------ FuncDeclNode ---------------------------------
2097 RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2099 if (dst == generator.ignoredResult())
2104 // ------------------------------ FuncExprNode ---------------------------------
2106 RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2108 return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);