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 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>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
28 #include "NodeConstructors.h"
30 #include "BytecodeGenerator.h"
31 #include "CallFrame.h"
34 #include "JSFunction.h"
35 #include "JSGlobalObject.h"
36 #include "JSStaticScopeObject.h"
37 #include "LabelScope.h"
39 #include "Operations.h"
41 #include "PropertyNameArray.h"
42 #include "RegExpCache.h"
43 #include "RegExpObject.h"
44 #include "SamplingTool.h"
45 #include "UStringConcatenate.h"
46 #include <wtf/Assertions.h>
47 #include <wtf/RefCountedLeakCounter.h>
48 #include <wtf/Threading.h>
55 Details of the emitBytecode function.
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.
61 The dst argument provides for a crude form of copy propagation. For example,
74 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
77 // ------------------------------ ThrowableExpressionData --------------------------------
79 RegisterID
* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator
& generator
, const UString
& message
)
81 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
82 generator
.emitThrowReferenceError(message
);
83 return generator
.newTemporary();
86 // ------------------------------ NullNode -------------------------------------
88 RegisterID
* NullNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
90 if (dst
== generator
.ignoredResult())
92 return generator
.emitLoad(dst
, jsNull());
95 // ------------------------------ BooleanNode ----------------------------------
97 RegisterID
* BooleanNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
99 if (dst
== generator
.ignoredResult())
101 return generator
.emitLoad(dst
, m_value
);
104 // ------------------------------ NumberNode -----------------------------------
106 RegisterID
* NumberNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
108 if (dst
== generator
.ignoredResult())
110 return generator
.emitLoad(dst
, m_value
);
113 // ------------------------------ StringNode -----------------------------------
115 RegisterID
* StringNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
117 if (dst
== generator
.ignoredResult())
119 return generator
.emitLoad(dst
, m_value
);
122 // ------------------------------ RegExpNode -----------------------------------
124 RegisterID
* RegExpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
126 if (dst
== generator
.ignoredResult())
128 return generator
.emitNewRegExp(generator
.finalDestination(dst
), RegExp::create(generator
.globalData(), m_pattern
.ustring(), regExpFlags(m_flags
.ustring())));
131 // ------------------------------ ThisNode -------------------------------------
133 RegisterID
* ThisNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
135 if (dst
== generator
.ignoredResult())
137 return generator
.moveToDestinationIfNeeded(dst
, generator
.thisRegister());
140 // ------------------------------ ResolveNode ----------------------------------
142 bool ResolveNode::isPure(BytecodeGenerator
& generator
) const
144 return generator
.isLocal(m_ident
);
147 RegisterID
* ResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
149 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
150 if (dst
== generator
.ignoredResult())
152 return generator
.moveToDestinationIfNeeded(dst
, local
);
155 generator
.emitExpressionInfo(m_startOffset
+ m_ident
.length(), m_ident
.length(), 0);
156 return generator
.emitResolve(generator
.finalDestination(dst
), m_ident
);
159 // ------------------------------ ArrayNode ------------------------------------
161 RegisterID
* ArrayNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
163 // FIXME: Should we put all of this code into emitNewArray?
166 ElementNode
* firstPutElement
;
167 for (firstPutElement
= m_element
; firstPutElement
; firstPutElement
= firstPutElement
->next()) {
168 if (firstPutElement
->elision())
173 if (!firstPutElement
&& !m_elision
)
174 return generator
.emitNewArray(generator
.finalDestination(dst
), m_element
, length
);
176 RefPtr
<RegisterID
> array
= generator
.emitNewArray(generator
.tempDestination(dst
), m_element
, length
);
178 for (ElementNode
* n
= firstPutElement
; n
; n
= n
->next()) {
179 RegisterID
* value
= generator
.emitNode(n
->value());
180 length
+= n
->elision();
181 generator
.emitPutByIndex(array
.get(), length
++, value
);
185 RegisterID
* value
= generator
.emitLoad(0, jsNumber(m_elision
+ length
));
186 generator
.emitPutById(array
.get(), generator
.propertyNames().length
, value
);
189 return generator
.moveToDestinationIfNeeded(dst
, array
.get());
192 bool ArrayNode::isSimpleArray() const
194 if (m_elision
|| m_optional
)
196 for (ElementNode
* ptr
= m_element
; ptr
; ptr
= ptr
->next()) {
203 ArgumentListNode
* ArrayNode::toArgumentList(JSGlobalData
* globalData
) const
205 ASSERT(!m_elision
&& !m_optional
);
206 ElementNode
* ptr
= m_element
;
209 ArgumentListNode
* head
= new (globalData
) ArgumentListNode(globalData
, ptr
->value());
210 ArgumentListNode
* tail
= head
;
212 for (; ptr
; ptr
= ptr
->next()) {
213 ASSERT(!ptr
->elision());
214 tail
= new (globalData
) ArgumentListNode(globalData
, tail
, ptr
->value());
219 // ------------------------------ ObjectLiteralNode ----------------------------
221 RegisterID
* ObjectLiteralNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
224 if (dst
== generator
.ignoredResult())
226 return generator
.emitNewObject(generator
.finalDestination(dst
));
228 return generator
.emitNode(dst
, m_list
);
231 // ------------------------------ PropertyListNode -----------------------------
233 RegisterID
* PropertyListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
235 RefPtr
<RegisterID
> newObj
= generator
.tempDestination(dst
);
237 generator
.emitNewObject(newObj
.get());
239 for (PropertyListNode
* p
= this; p
; p
= p
->m_next
) {
240 RegisterID
* value
= generator
.emitNode(p
->m_node
->m_assign
);
242 switch (p
->m_node
->m_type
) {
243 case PropertyNode::Constant
: {
244 generator
.emitDirectPutById(newObj
.get(), p
->m_node
->name(), value
);
247 case PropertyNode::Getter
: {
248 generator
.emitPutGetter(newObj
.get(), p
->m_node
->name(), value
);
251 case PropertyNode::Setter
: {
252 generator
.emitPutSetter(newObj
.get(), p
->m_node
->name(), value
);
256 ASSERT_NOT_REACHED();
260 return generator
.moveToDestinationIfNeeded(dst
, newObj
.get());
263 // ------------------------------ BracketAccessorNode --------------------------------
265 RegisterID
* BracketAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
267 if (m_base
->isResolveNode() && generator
.willResolveToArguments(static_cast<ResolveNode
*>(m_base
)->identifier())) {
268 RegisterID
* property
= generator
.emitNode(m_subscript
);
269 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
270 return generator
.emitGetArgumentByVal(generator
.finalDestination(dst
), generator
.uncheckedRegisterForArguments(), property
);
273 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
, m_subscript
->isPure(generator
));
274 RegisterID
* property
= generator
.emitNode(m_subscript
);
275 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
276 return generator
.emitGetByVal(generator
.finalDestination(dst
), base
.get(), property
);
279 // ------------------------------ DotAccessorNode --------------------------------
281 RegisterID
* DotAccessorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
283 if (m_ident
== generator
.propertyNames().length
) {
284 if (!m_base
->isResolveNode())
285 goto nonArgumentsPath
;
286 ResolveNode
* resolveNode
= static_cast<ResolveNode
*>(m_base
);
287 if (!generator
.willResolveToArguments(resolveNode
->identifier()))
288 goto nonArgumentsPath
;
289 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
290 return generator
.emitGetArgumentsLength(generator
.finalDestination(dst
), generator
.uncheckedRegisterForArguments());
294 RegisterID
* base
= generator
.emitNode(m_base
);
295 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
296 return generator
.emitGetById(generator
.finalDestination(dst
), base
, m_ident
);
299 // ------------------------------ ArgumentListNode -----------------------------
301 RegisterID
* ArgumentListNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
304 return generator
.emitNode(dst
, m_expr
);
307 // ------------------------------ NewExprNode ----------------------------------
309 RegisterID
* NewExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
311 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
312 CallArguments
callArguments(generator
, m_args
);
313 return generator
.emitConstruct(generator
.finalDestinationOrIgnored(dst
), func
.get(), callArguments
, divot(), startOffset(), endOffset());
316 CallArguments::CallArguments(BytecodeGenerator
& generator
, ArgumentsNode
* argumentsNode
)
317 : m_argumentsNode(argumentsNode
)
319 if (generator
.shouldEmitProfileHooks())
320 m_profileHookRegister
= generator
.newTemporary();
321 m_argv
.append(generator
.newTemporary());
323 for (ArgumentListNode
* n
= argumentsNode
->m_listNode
; n
; n
= n
->m_next
) {
324 m_argv
.append(generator
.newTemporary());
325 // op_call requires the arguments to be a sequential range of registers
326 ASSERT(m_argv
[m_argv
.size() - 1]->index() == m_argv
[m_argv
.size() - 2]->index() + 1);
331 // ------------------------------ EvalFunctionCallNode ----------------------------------
333 RegisterID
* EvalFunctionCallNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
335 RefPtr
<RegisterID
> func
= generator
.tempDestination(dst
);
336 CallArguments
callArguments(generator
, m_args
);
337 generator
.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
338 generator
.emitResolveWithBase(callArguments
.thisRegister(), func
.get(), generator
.propertyNames().eval
);
339 return generator
.emitCallEval(generator
.finalDestination(dst
, func
.get()), func
.get(), callArguments
, divot(), startOffset(), endOffset());
342 // ------------------------------ FunctionCallValueNode ----------------------------------
344 RegisterID
* FunctionCallValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
346 RefPtr
<RegisterID
> func
= generator
.emitNode(m_expr
);
347 CallArguments
callArguments(generator
, m_args
);
348 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
349 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, func
.get()), func
.get(), callArguments
, divot(), startOffset(), endOffset());
352 // ------------------------------ FunctionCallResolveNode ----------------------------------
354 RegisterID
* FunctionCallResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
356 if (RefPtr
<RegisterID
> local
= generator
.registerFor(m_ident
)) {
357 CallArguments
callArguments(generator
, m_args
);
358 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
359 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, callArguments
.thisRegister()), local
.get(), callArguments
, divot(), startOffset(), endOffset());
364 JSObject
* globalObject
= 0;
365 bool requiresDynamicChecks
= false;
366 if (generator
.findScopedProperty(m_ident
, index
, depth
, false, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
367 RefPtr
<RegisterID
> func
= generator
.emitGetScopedVar(generator
.newTemporary(), depth
, index
, globalObject
);
368 CallArguments
callArguments(generator
, m_args
);
369 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
370 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, func
.get()), func
.get(), callArguments
, divot(), startOffset(), endOffset());
373 RefPtr
<RegisterID
> func
= generator
.newTemporary();
374 CallArguments
callArguments(generator
, m_args
);
375 int identifierStart
= divot() - startOffset();
376 generator
.emitExpressionInfo(identifierStart
+ m_ident
.length(), m_ident
.length(), 0);
377 generator
.emitResolveWithBase(callArguments
.thisRegister(), func
.get(), m_ident
);
378 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, func
.get()), func
.get(), callArguments
, divot(), startOffset(), endOffset());
381 // ------------------------------ FunctionCallBracketNode ----------------------------------
383 RegisterID
* FunctionCallBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
385 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
386 RegisterID
* property
= generator
.emitNode(m_subscript
);
387 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
388 RefPtr
<RegisterID
> function
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
);
389 CallArguments
callArguments(generator
, m_args
);
390 generator
.emitMove(callArguments
.thisRegister(), base
.get());
391 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, function
.get()), function
.get(), callArguments
, divot(), startOffset(), endOffset());
394 // ------------------------------ FunctionCallDotNode ----------------------------------
396 RegisterID
* FunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
398 RefPtr
<RegisterID
> function
= generator
.tempDestination(dst
);
399 CallArguments
callArguments(generator
, m_args
);
400 generator
.emitNode(callArguments
.thisRegister(), m_base
);
401 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
402 generator
.emitMethodCheck();
403 generator
.emitGetById(function
.get(), callArguments
.thisRegister(), m_ident
);
404 return generator
.emitCall(generator
.finalDestinationOrIgnored(dst
, function
.get()), function
.get(), callArguments
, divot(), startOffset(), endOffset());
407 RegisterID
* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
409 RefPtr
<Label
> realCall
= generator
.newLabel();
410 RefPtr
<Label
> end
= generator
.newLabel();
411 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
412 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
413 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
414 RefPtr
<RegisterID
> finalDestinationOrIgnored
= generator
.finalDestinationOrIgnored(dst
, function
.get());
415 generator
.emitJumpIfNotFunctionCall(function
.get(), realCall
.get());
417 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
418 ArgumentListNode
* oldList
= m_args
->m_listNode
;
419 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
421 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
422 CallArguments
callArguments(generator
, m_args
);
423 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
424 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), callArguments
, divot(), startOffset(), endOffset());
425 generator
.emitJump(end
.get());
427 m_args
->m_listNode
= oldList
;
430 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
431 CallArguments
callArguments(generator
, m_args
);
432 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
433 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), callArguments
, divot(), startOffset(), endOffset());
434 generator
.emitJump(end
.get());
437 generator
.emitLabel(realCall
.get());
439 CallArguments
callArguments(generator
, m_args
);
440 generator
.emitMove(callArguments
.thisRegister(), base
.get());
441 generator
.emitCall(finalDestinationOrIgnored
.get(), function
.get(), callArguments
, divot(), startOffset(), endOffset());
443 generator
.emitLabel(end
.get());
444 return finalDestinationOrIgnored
.get();
447 static bool areTrivialApplyArguments(ArgumentsNode
* args
)
449 return !args
->m_listNode
|| !args
->m_listNode
->m_expr
|| !args
->m_listNode
->m_next
450 || (!args
->m_listNode
->m_next
->m_next
&& args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
453 RegisterID
* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
455 // A few simple cases can be trivially handled as ordinary function calls.
456 // function.apply(), function.apply(arg) -> identical to function.call
457 // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation
458 bool mayBeCall
= areTrivialApplyArguments(m_args
);
460 RefPtr
<Label
> realCall
= generator
.newLabel();
461 RefPtr
<Label
> end
= generator
.newLabel();
462 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
463 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
464 RefPtr
<RegisterID
> function
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
465 RefPtr
<RegisterID
> finalDestinationOrIgnored
= generator
.finalDestinationOrIgnored(dst
, function
.get());
466 generator
.emitJumpIfNotFunctionApply(function
.get(), realCall
.get());
469 if (m_args
->m_listNode
&& m_args
->m_listNode
->m_expr
) {
470 ArgumentListNode
* oldList
= m_args
->m_listNode
;
471 if (m_args
->m_listNode
->m_next
) {
472 ASSERT(m_args
->m_listNode
->m_next
->m_expr
->isSimpleArray());
473 ASSERT(!m_args
->m_listNode
->m_next
->m_next
);
474 m_args
->m_listNode
= static_cast<ArrayNode
*>(m_args
->m_listNode
->m_next
->m_expr
)->toArgumentList(generator
.globalData());
475 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
476 CallArguments
callArguments(generator
, m_args
);
477 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
478 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), callArguments
, divot(), startOffset(), endOffset());
480 m_args
->m_listNode
= m_args
->m_listNode
->m_next
;
481 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
482 CallArguments
callArguments(generator
, m_args
);
483 generator
.emitNode(callArguments
.thisRegister(), oldList
->m_expr
);
484 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), callArguments
, divot(), startOffset(), endOffset());
486 m_args
->m_listNode
= oldList
;
488 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.tempDestination(dst
), base
.get());
489 CallArguments
callArguments(generator
, m_args
);
490 generator
.emitLoad(callArguments
.thisRegister(), jsUndefined());
491 generator
.emitCall(finalDestinationOrIgnored
.get(), realFunction
.get(), callArguments
, divot(), startOffset(), endOffset());
494 ASSERT(m_args
->m_listNode
&& m_args
->m_listNode
->m_next
);
495 RefPtr
<RegisterID
> realFunction
= generator
.emitMove(generator
.newTemporary(), base
.get());
496 RefPtr
<RegisterID
> argsCountRegister
= generator
.newTemporary();
497 RefPtr
<RegisterID
> thisRegister
= generator
.newTemporary();
498 RefPtr
<RegisterID
> argsRegister
= generator
.newTemporary();
499 generator
.emitNode(thisRegister
.get(), m_args
->m_listNode
->m_expr
);
500 ArgumentListNode
* args
= m_args
->m_listNode
->m_next
;
501 bool isArgumentsApply
= false;
502 if (args
->m_expr
->isResolveNode()) {
503 ResolveNode
* resolveNode
= static_cast<ResolveNode
*>(args
->m_expr
);
504 isArgumentsApply
= generator
.willResolveToArguments(resolveNode
->identifier());
505 if (isArgumentsApply
)
506 generator
.emitMove(argsRegister
.get(), generator
.uncheckedRegisterForArguments());
508 if (!isArgumentsApply
)
509 generator
.emitNode(argsRegister
.get(), args
->m_expr
);
510 while ((args
= args
->m_next
))
511 generator
.emitNode(args
->m_expr
);
513 generator
.emitLoadVarargs(argsCountRegister
.get(), thisRegister
.get(), argsRegister
.get());
514 generator
.emitCallVarargs(finalDestinationOrIgnored
.get(), realFunction
.get(), thisRegister
.get(), argsCountRegister
.get(), divot(), startOffset(), endOffset());
516 generator
.emitJump(end
.get());
518 generator
.emitLabel(realCall
.get());
520 CallArguments
callArguments(generator
, m_args
);
521 generator
.emitMove(callArguments
.thisRegister(), base
.get());
522 generator
.emitCall(finalDestinationOrIgnored
.get(), function
.get(), callArguments
, divot(), startOffset(), endOffset());
524 generator
.emitLabel(end
.get());
525 return finalDestinationOrIgnored
.get();
528 // ------------------------------ PostfixResolveNode ----------------------------------
530 static RegisterID
* emitPreIncOrDec(BytecodeGenerator
& generator
, RegisterID
* srcDst
, Operator oper
)
532 return (oper
== OpPlusPlus
) ? generator
.emitPreInc(srcDst
) : generator
.emitPreDec(srcDst
);
535 static RegisterID
* emitPostIncOrDec(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* srcDst
, Operator oper
)
538 return generator
.emitToJSNumber(dst
, srcDst
);
539 return (oper
== OpPlusPlus
) ? generator
.emitPostInc(dst
, srcDst
) : generator
.emitPostDec(dst
, srcDst
);
542 RegisterID
* PostfixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
544 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
545 if (generator
.isLocalConstant(m_ident
)) {
546 if (dst
== generator
.ignoredResult())
548 return generator
.emitToJSNumber(generator
.finalDestination(dst
), local
);
551 if (dst
== generator
.ignoredResult())
552 return emitPreIncOrDec(generator
, local
, m_operator
);
553 return emitPostIncOrDec(generator
, generator
.finalDestination(dst
), local
, m_operator
);
558 JSObject
* globalObject
= 0;
559 bool requiresDynamicChecks
= false;
560 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
561 RefPtr
<RegisterID
> value
= generator
.emitGetScopedVar(generator
.newTemporary(), depth
, index
, globalObject
);
562 RegisterID
* oldValue
;
563 if (dst
== generator
.ignoredResult()) {
565 emitPreIncOrDec(generator
, value
.get(), m_operator
);
567 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
569 generator
.emitPutScopedVar(depth
, index
, value
.get(), globalObject
);
573 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
574 RefPtr
<RegisterID
> value
= generator
.newTemporary();
575 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), value
.get(), m_ident
);
576 RegisterID
* oldValue
;
577 if (dst
== generator
.ignoredResult()) {
579 emitPreIncOrDec(generator
, value
.get(), m_operator
);
581 oldValue
= emitPostIncOrDec(generator
, generator
.finalDestination(dst
), value
.get(), m_operator
);
583 generator
.emitPutById(base
.get(), m_ident
, value
.get());
587 // ------------------------------ PostfixBracketNode ----------------------------------
589 RegisterID
* PostfixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
591 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
592 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
594 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
595 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.newTemporary(), base
.get(), property
.get());
596 RegisterID
* oldValue
;
597 if (dst
== generator
.ignoredResult()) {
599 if (m_operator
== OpPlusPlus
)
600 generator
.emitPreInc(value
.get());
602 generator
.emitPreDec(value
.get());
604 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
606 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
607 generator
.emitPutByVal(base
.get(), property
.get(), value
.get());
611 // ------------------------------ PostfixDotNode ----------------------------------
613 RegisterID
* PostfixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
615 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
617 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
618 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.newTemporary(), base
.get(), m_ident
);
619 RegisterID
* oldValue
;
620 if (dst
== generator
.ignoredResult()) {
622 if (m_operator
== OpPlusPlus
)
623 generator
.emitPreInc(value
.get());
625 generator
.emitPreDec(value
.get());
627 oldValue
= (m_operator
== OpPlusPlus
) ? generator
.emitPostInc(generator
.finalDestination(dst
), value
.get()) : generator
.emitPostDec(generator
.finalDestination(dst
), value
.get());
629 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
630 generator
.emitPutById(base
.get(), m_ident
, value
.get());
634 // ------------------------------ PostfixErrorNode -----------------------------------
636 RegisterID
* PostfixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
638 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
639 ? "Postfix ++ operator applied to value that is not a reference."
640 : "Postfix -- operator applied to value that is not a reference.");
643 // ------------------------------ DeleteResolveNode -----------------------------------
645 RegisterID
* DeleteResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
647 if (generator
.registerFor(m_ident
))
648 return generator
.emitLoad(generator
.finalDestination(dst
), false);
650 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
651 RegisterID
* base
= generator
.emitResolveBase(generator
.tempDestination(dst
), m_ident
);
652 return generator
.emitDeleteById(generator
.finalDestination(dst
, base
), base
, m_ident
);
655 // ------------------------------ DeleteBracketNode -----------------------------------
657 RegisterID
* DeleteBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
659 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_base
);
660 RegisterID
* r1
= generator
.emitNode(m_subscript
);
662 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
663 return generator
.emitDeleteByVal(generator
.finalDestination(dst
), r0
.get(), r1
);
666 // ------------------------------ DeleteDotNode -----------------------------------
668 RegisterID
* DeleteDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
670 RegisterID
* r0
= generator
.emitNode(m_base
);
672 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
673 return generator
.emitDeleteById(generator
.finalDestination(dst
), r0
, m_ident
);
676 // ------------------------------ DeleteValueNode -----------------------------------
678 RegisterID
* DeleteValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
680 generator
.emitNode(generator
.ignoredResult(), m_expr
);
682 // delete on a non-location expression ignores the value and returns true
683 return generator
.emitLoad(generator
.finalDestination(dst
), true);
686 // ------------------------------ VoidNode -------------------------------------
688 RegisterID
* VoidNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
690 if (dst
== generator
.ignoredResult()) {
691 generator
.emitNode(generator
.ignoredResult(), m_expr
);
694 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
695 return generator
.emitLoad(dst
, jsUndefined());
698 // ------------------------------ TypeOfValueNode -----------------------------------
700 RegisterID
* TypeOfResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
702 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
703 if (dst
== generator
.ignoredResult())
705 return generator
.emitTypeOf(generator
.finalDestination(dst
), local
);
708 RefPtr
<RegisterID
> scratch
= generator
.emitResolveBase(generator
.tempDestination(dst
), m_ident
);
709 generator
.emitGetById(scratch
.get(), scratch
.get(), m_ident
);
710 if (dst
== generator
.ignoredResult())
712 return generator
.emitTypeOf(generator
.finalDestination(dst
, scratch
.get()), scratch
.get());
715 // ------------------------------ TypeOfValueNode -----------------------------------
717 RegisterID
* TypeOfValueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
719 if (dst
== generator
.ignoredResult()) {
720 generator
.emitNode(generator
.ignoredResult(), m_expr
);
723 RefPtr
<RegisterID
> src
= generator
.emitNode(m_expr
);
724 return generator
.emitTypeOf(generator
.finalDestination(dst
), src
.get());
727 // ------------------------------ PrefixResolveNode ----------------------------------
729 RegisterID
* PrefixResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
731 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
732 if (generator
.isLocalConstant(m_ident
)) {
733 if (dst
== generator
.ignoredResult())
735 RefPtr
<RegisterID
> r0
= generator
.emitLoad(generator
.finalDestination(dst
), (m_operator
== OpPlusPlus
) ? 1.0 : -1.0);
736 return generator
.emitBinaryOp(op_add
, r0
.get(), local
, r0
.get(), OperandTypes());
739 emitPreIncOrDec(generator
, local
, m_operator
);
740 return generator
.moveToDestinationIfNeeded(dst
, local
);
745 JSObject
* globalObject
= 0;
746 bool requiresDynamicChecks
= false;
747 if (generator
.findScopedProperty(m_ident
, index
, depth
, false, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
748 RefPtr
<RegisterID
> propDst
= generator
.emitGetScopedVar(generator
.tempDestination(dst
), depth
, index
, globalObject
);
749 emitPreIncOrDec(generator
, propDst
.get(), m_operator
);
750 generator
.emitPutScopedVar(depth
, index
, propDst
.get(), globalObject
);
751 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
754 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
755 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
756 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), propDst
.get(), m_ident
);
757 emitPreIncOrDec(generator
, propDst
.get(), m_operator
);
758 generator
.emitPutById(base
.get(), m_ident
, propDst
.get());
759 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
762 // ------------------------------ PrefixBracketNode ----------------------------------
764 RegisterID
* PrefixBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
766 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
767 RefPtr
<RegisterID
> property
= generator
.emitNode(m_subscript
);
768 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
770 generator
.emitExpressionInfo(divot() + m_subexpressionDivotOffset
, m_subexpressionStartOffset
, endOffset() - m_subexpressionDivotOffset
);
771 RegisterID
* value
= generator
.emitGetByVal(propDst
.get(), base
.get(), property
.get());
772 if (m_operator
== OpPlusPlus
)
773 generator
.emitPreInc(value
);
775 generator
.emitPreDec(value
);
776 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
777 generator
.emitPutByVal(base
.get(), property
.get(), value
);
778 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
781 // ------------------------------ PrefixDotNode ----------------------------------
783 RegisterID
* PrefixDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
785 RefPtr
<RegisterID
> base
= generator
.emitNode(m_base
);
786 RefPtr
<RegisterID
> propDst
= generator
.tempDestination(dst
);
788 generator
.emitExpressionInfo(divot() + m_subexpressionDivotOffset
, m_subexpressionStartOffset
, endOffset() - m_subexpressionDivotOffset
);
789 RegisterID
* value
= generator
.emitGetById(propDst
.get(), base
.get(), m_ident
);
790 if (m_operator
== OpPlusPlus
)
791 generator
.emitPreInc(value
);
793 generator
.emitPreDec(value
);
794 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
795 generator
.emitPutById(base
.get(), m_ident
, value
);
796 return generator
.moveToDestinationIfNeeded(dst
, propDst
.get());
799 // ------------------------------ PrefixErrorNode -----------------------------------
801 RegisterID
* PrefixErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
803 return emitThrowReferenceError(generator
, m_operator
== OpPlusPlus
804 ? "Prefix ++ operator applied to value that is not a reference."
805 : "Prefix -- operator applied to value that is not a reference.");
808 // ------------------------------ Unary Operation Nodes -----------------------------------
810 RegisterID
* UnaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
812 RegisterID
* src
= generator
.emitNode(m_expr
);
813 return generator
.emitUnaryOp(opcodeID(), generator
.finalDestination(dst
), src
);
817 // ------------------------------ LogicalNotNode -----------------------------------
819 void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
821 ASSERT(expr()->hasConditionContextCodegen());
823 // reverse the true and false targets
824 generator
.emitNodeInConditionContext(expr(), falseTarget
, trueTarget
, !fallThroughMeansTrue
);
828 // ------------------------------ Binary Operation Nodes -----------------------------------
830 // BinaryOpNode::emitStrcat:
832 // This node generates an op_strcat operation. This opcode can handle concatenation of three or
833 // more values, where we can determine a set of separate op_add operations would be operating on
836 // This function expects to be operating on a graph of AST nodes looking something like this:
846 // The assignment operation is optional, if it exists the register holding the value on the
847 // lefthand side of the assignment should be passing as the optional 'lhs' argument.
849 // The method should be called on the node at the root of the tree of regular binary add
850 // operations (marked in the diagram with a double set of parentheses). This node must
851 // be performing a string concatenation (determined by statically detecting that at least
852 // one child must be a string).
854 // Since the minimum number of values being concatenated together is expected to be 3, if
855 // a lhs to a concatenating assignment is not provided then the root add should have at
856 // least one left child that is also an add that can be determined to be operating on strings.
858 RegisterID
* BinaryOpNode::emitStrcat(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* lhs
, ReadModifyResolveNode
* emitExpressionInfoForMe
)
861 ASSERT(resultDescriptor().definitelyIsString());
863 // Create a list of expressions for all the adds in the tree of nodes we can convert into
864 // a string concatenation. The rightmost node (c) is added first. The rightmost node is
865 // added first, and the leftmost child is never added, so the vector produced for the
866 // example above will be [ c, b ].
867 Vector
<ExpressionNode
*, 16> reverseExpressionList
;
868 reverseExpressionList
.append(m_expr2
);
870 // Examine the left child of the add. So long as this is a string add, add its right-child
871 // to the list, and keep processing along the left fork.
872 ExpressionNode
* leftMostAddChild
= m_expr1
;
873 while (leftMostAddChild
->isAdd() && leftMostAddChild
->resultDescriptor().definitelyIsString()) {
874 reverseExpressionList
.append(static_cast<AddNode
*>(leftMostAddChild
)->m_expr2
);
875 leftMostAddChild
= static_cast<AddNode
*>(leftMostAddChild
)->m_expr1
;
878 Vector
<RefPtr
<RegisterID
>, 16> temporaryRegisters
;
880 // If there is an assignment, allocate a temporary to hold the lhs after conversion.
881 // We could possibly avoid this (the lhs is converted last anyway, we could let the
882 // op_strcat node handle its conversion if required).
884 temporaryRegisters
.append(generator
.newTemporary());
886 // Emit code for the leftmost node ((a) in the example).
887 temporaryRegisters
.append(generator
.newTemporary());
888 RegisterID
* leftMostAddChildTempRegister
= temporaryRegisters
.last().get();
889 generator
.emitNode(leftMostAddChildTempRegister
, leftMostAddChild
);
891 // Note on ordering of conversions:
893 // We maintain the same ordering of conversions as we would see if the concatenations
894 // was performed as a sequence of adds (otherwise this optimization could change
895 // behaviour should an object have been provided a valueOf or toString method).
897 // Considering the above example, the sequnce of execution is:
898 // * evaluate operand (a)
899 // * evaluate operand (b)
900 // * convert (a) to primitive <- (this would be triggered by the first add)
901 // * convert (b) to primitive <- (ditto)
902 // * evaluate operand (c)
903 // * convert (c) to primitive <- (this would be triggered by the second add)
904 // And optionally, if there is an assignment:
905 // * convert (d) to primitive <- (this would be triggered by the assigning addition)
907 // As such we do not plant an op to convert the leftmost child now. Instead, use
908 // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion
909 // once the second node has been generated. However, if the leftmost child is an
910 // immediate we can trivially determine that no conversion will be required.
911 // If this is the case
912 if (leftMostAddChild
->isString())
913 leftMostAddChildTempRegister
= 0;
915 while (reverseExpressionList
.size()) {
916 ExpressionNode
* node
= reverseExpressionList
.last();
917 reverseExpressionList
.removeLast();
919 // Emit the code for the current node.
920 temporaryRegisters
.append(generator
.newTemporary());
921 generator
.emitNode(temporaryRegisters
.last().get(), node
);
923 // On the first iteration of this loop, when we first reach this point we have just
924 // generated the second node, which means it is time to convert the leftmost operand.
925 if (leftMostAddChildTempRegister
) {
926 generator
.emitToPrimitive(leftMostAddChildTempRegister
, leftMostAddChildTempRegister
);
927 leftMostAddChildTempRegister
= 0; // Only do this once.
929 // Plant a conversion for this node, if necessary.
930 if (!node
->isString())
931 generator
.emitToPrimitive(temporaryRegisters
.last().get(), temporaryRegisters
.last().get());
933 ASSERT(temporaryRegisters
.size() >= 3);
935 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
936 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
937 if (emitExpressionInfoForMe
)
938 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
940 // If there is an assignment convert the lhs now. This will also copy lhs to
941 // the temporary register we allocated for it.
943 generator
.emitToPrimitive(temporaryRegisters
[0].get(), lhs
);
945 return generator
.emitStrcat(generator
.finalDestination(dst
, temporaryRegisters
[0].get()), temporaryRegisters
[0].get(), temporaryRegisters
.size());
948 RegisterID
* BinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
950 OpcodeID opcodeID
= this->opcodeID();
952 if (opcodeID
== op_add
&& m_expr1
->isAdd() && m_expr1
->resultDescriptor().definitelyIsString())
953 return emitStrcat(generator
, dst
);
955 if (opcodeID
== op_neq
) {
956 if (m_expr1
->isNull() || m_expr2
->isNull()) {
957 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
958 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
959 return generator
.emitUnaryOp(op_neq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
963 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
964 RegisterID
* src2
= generator
.emitNode(m_expr2
);
965 return generator
.emitBinaryOp(opcodeID
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
968 RegisterID
* EqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
970 if (m_expr1
->isNull() || m_expr2
->isNull()) {
971 RefPtr
<RegisterID
> src
= generator
.tempDestination(dst
);
972 generator
.emitNode(src
.get(), m_expr1
->isNull() ? m_expr2
: m_expr1
);
973 return generator
.emitUnaryOp(op_eq_null
, generator
.finalDestination(dst
, src
.get()), src
.get());
976 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
977 RegisterID
* src2
= generator
.emitNode(m_expr2
);
978 return generator
.emitEqualityOp(op_eq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
981 RegisterID
* StrictEqualNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
983 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
984 RegisterID
* src2
= generator
.emitNode(m_expr2
);
985 return generator
.emitEqualityOp(op_stricteq
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
);
988 RegisterID
* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
990 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
991 RegisterID
* src2
= generator
.emitNode(m_expr2
);
992 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src2
, src1
.get(), OperandTypes(m_expr2
->resultDescriptor(), m_expr1
->resultDescriptor()));
995 RegisterID
* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
997 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
998 RegisterID
* src2
= generator
.emitNode(m_expr2
);
999 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1000 return generator
.emitBinaryOp(opcodeID(), generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
, OperandTypes(m_expr1
->resultDescriptor(), m_expr2
->resultDescriptor()));
1003 RegisterID
* InstanceOfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1005 RefPtr
<RegisterID
> src1
= generator
.emitNodeForLeftHandSide(m_expr1
, m_rightHasAssignments
, m_expr2
->isPure(generator
));
1006 RefPtr
<RegisterID
> src2
= generator
.emitNode(m_expr2
);
1008 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1009 generator
.emitCheckHasInstance(src2
.get());
1011 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1012 RegisterID
* src2Prototype
= generator
.emitGetById(generator
.newTemporary(), src2
.get(), generator
.globalData()->propertyNames
->prototype
);
1014 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1015 return generator
.emitInstanceOf(generator
.finalDestination(dst
, src1
.get()), src1
.get(), src2
.get(), src2Prototype
);
1018 // ------------------------------ LogicalOpNode ----------------------------
1020 RegisterID
* LogicalOpNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1022 RefPtr
<RegisterID
> temp
= generator
.tempDestination(dst
);
1023 RefPtr
<Label
> target
= generator
.newLabel();
1025 generator
.emitNode(temp
.get(), m_expr1
);
1026 if (m_operator
== OpLogicalAnd
)
1027 generator
.emitJumpIfFalse(temp
.get(), target
.get());
1029 generator
.emitJumpIfTrue(temp
.get(), target
.get());
1030 generator
.emitNode(temp
.get(), m_expr2
);
1031 generator
.emitLabel(target
.get());
1033 return generator
.moveToDestinationIfNeeded(dst
, temp
.get());
1036 void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator
& generator
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
1038 if (m_expr1
->hasConditionContextCodegen()) {
1039 RefPtr
<Label
> afterExpr1
= generator
.newLabel();
1040 if (m_operator
== OpLogicalAnd
)
1041 generator
.emitNodeInConditionContext(m_expr1
, afterExpr1
.get(), falseTarget
, true);
1043 generator
.emitNodeInConditionContext(m_expr1
, trueTarget
, afterExpr1
.get(), false);
1044 generator
.emitLabel(afterExpr1
.get());
1046 RegisterID
* temp
= generator
.emitNode(m_expr1
);
1047 if (m_operator
== OpLogicalAnd
)
1048 generator
.emitJumpIfFalse(temp
, falseTarget
);
1050 generator
.emitJumpIfTrue(temp
, trueTarget
);
1053 if (m_expr2
->hasConditionContextCodegen())
1054 generator
.emitNodeInConditionContext(m_expr2
, trueTarget
, falseTarget
, fallThroughMeansTrue
);
1056 RegisterID
* temp
= generator
.emitNode(m_expr2
);
1057 if (fallThroughMeansTrue
)
1058 generator
.emitJumpIfFalse(temp
, falseTarget
);
1060 generator
.emitJumpIfTrue(temp
, trueTarget
);
1064 // ------------------------------ ConditionalNode ------------------------------
1066 RegisterID
* ConditionalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1068 RefPtr
<RegisterID
> newDst
= generator
.finalDestination(dst
);
1069 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1070 RefPtr
<Label
> afterElse
= generator
.newLabel();
1072 if (m_logical
->hasConditionContextCodegen()) {
1073 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1074 generator
.emitNodeInConditionContext(m_logical
, beforeThen
.get(), beforeElse
.get(), true);
1075 generator
.emitLabel(beforeThen
.get());
1077 RegisterID
* cond
= generator
.emitNode(m_logical
);
1078 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1081 generator
.emitNode(newDst
.get(), m_expr1
);
1082 generator
.emitJump(afterElse
.get());
1084 generator
.emitLabel(beforeElse
.get());
1085 generator
.emitNode(newDst
.get(), m_expr2
);
1087 generator
.emitLabel(afterElse
.get());
1089 return newDst
.get();
1092 // ------------------------------ ReadModifyResolveNode -----------------------------------
1094 // FIXME: should this be moved to be a method on BytecodeGenerator?
1095 static ALWAYS_INLINE RegisterID
* emitReadModifyAssignment(BytecodeGenerator
& generator
, RegisterID
* dst
, RegisterID
* src1
, ExpressionNode
* m_right
, Operator oper
, OperandTypes types
, ReadModifyResolveNode
* emitExpressionInfoForMe
= 0)
1106 if (m_right
->isAdd() && m_right
->resultDescriptor().definitelyIsString())
1107 return static_cast<AddNode
*>(m_right
)->emitStrcat(generator
, dst
, src1
, emitExpressionInfoForMe
);
1114 opcodeID
= op_lshift
;
1117 opcodeID
= op_rshift
;
1120 opcodeID
= op_urshift
;
1123 opcodeID
= op_bitand
;
1126 opcodeID
= op_bitxor
;
1129 opcodeID
= op_bitor
;
1135 ASSERT_NOT_REACHED();
1139 RegisterID
* src2
= generator
.emitNode(m_right
);
1141 // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated.
1142 // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
1143 if (emitExpressionInfoForMe
)
1144 generator
.emitExpressionInfo(emitExpressionInfoForMe
->divot(), emitExpressionInfoForMe
->startOffset(), emitExpressionInfoForMe
->endOffset());
1146 return generator
.emitBinaryOp(opcodeID
, dst
, src1
, src2
, types
);
1149 RegisterID
* ReadModifyResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1151 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1152 if (generator
.isLocalConstant(m_ident
)) {
1153 return emitReadModifyAssignment(generator
, generator
.finalDestination(dst
), local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1156 if (generator
.leftHandSideNeedsCopy(m_rightHasAssignments
, m_right
->isPure(generator
))) {
1157 RefPtr
<RegisterID
> result
= generator
.newTemporary();
1158 generator
.emitMove(result
.get(), local
);
1159 emitReadModifyAssignment(generator
, result
.get(), result
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1160 generator
.emitMove(local
, result
.get());
1161 return generator
.moveToDestinationIfNeeded(dst
, result
.get());
1164 RegisterID
* result
= emitReadModifyAssignment(generator
, local
, local
, m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1165 return generator
.moveToDestinationIfNeeded(dst
, result
);
1170 JSObject
* globalObject
= 0;
1171 bool requiresDynamicChecks
= false;
1172 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
1173 RefPtr
<RegisterID
> src1
= generator
.emitGetScopedVar(generator
.tempDestination(dst
), depth
, index
, globalObject
);
1174 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1175 generator
.emitPutScopedVar(depth
, index
, result
, globalObject
);
1179 RefPtr
<RegisterID
> src1
= generator
.tempDestination(dst
);
1180 generator
.emitExpressionInfo(divot() - startOffset() + m_ident
.length(), m_ident
.length(), 0);
1181 RefPtr
<RegisterID
> base
= generator
.emitResolveWithBase(generator
.newTemporary(), src1
.get(), m_ident
);
1182 RegisterID
* result
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, src1
.get()), src1
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()), this);
1183 return generator
.emitPutById(base
.get(), m_ident
, result
);
1186 // ------------------------------ AssignResolveNode -----------------------------------
1188 RegisterID
* AssignResolveNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1190 if (RegisterID
* local
= generator
.registerFor(m_ident
)) {
1191 if (generator
.isLocalConstant(m_ident
))
1192 return generator
.emitNode(dst
, m_right
);
1194 RegisterID
* result
= generator
.emitNode(local
, m_right
);
1195 return generator
.moveToDestinationIfNeeded(dst
, result
);
1200 JSObject
* globalObject
= 0;
1201 bool requiresDynamicChecks
= false;
1202 if (generator
.findScopedProperty(m_ident
, index
, depth
, true, requiresDynamicChecks
, globalObject
) && index
!= missingSymbolMarker() && !requiresDynamicChecks
) {
1203 if (dst
== generator
.ignoredResult())
1205 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1206 generator
.emitPutScopedVar(depth
, index
, value
, globalObject
);
1210 RefPtr
<RegisterID
> base
= generator
.emitResolveBaseForPut(generator
.newTemporary(), m_ident
);
1211 if (dst
== generator
.ignoredResult())
1213 RegisterID
* value
= generator
.emitNode(dst
, m_right
);
1214 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1215 return generator
.emitPutById(base
.get(), m_ident
, value
);
1218 // ------------------------------ AssignDotNode -----------------------------------
1220 RegisterID
* AssignDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1222 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1223 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1224 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1225 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1226 generator
.emitPutById(base
.get(), m_ident
, result
);
1227 return generator
.moveToDestinationIfNeeded(dst
, result
);
1230 // ------------------------------ ReadModifyDotNode -----------------------------------
1232 RegisterID
* ReadModifyDotNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1234 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_rightHasAssignments
, m_right
->isPure(generator
));
1236 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1237 RefPtr
<RegisterID
> value
= generator
.emitGetById(generator
.tempDestination(dst
), base
.get(), m_ident
);
1238 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1240 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1241 return generator
.emitPutById(base
.get(), m_ident
, updatedValue
);
1244 // ------------------------------ AssignErrorNode -----------------------------------
1246 RegisterID
* AssignErrorNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1248 return emitThrowReferenceError(generator
, "Left side of assignment is not a reference.");
1251 // ------------------------------ AssignBracketNode -----------------------------------
1253 RegisterID
* AssignBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1255 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1256 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1257 RefPtr
<RegisterID
> value
= generator
.destinationForAssignResult(dst
);
1258 RegisterID
* result
= generator
.emitNode(value
.get(), m_right
);
1260 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1261 generator
.emitPutByVal(base
.get(), property
.get(), result
);
1262 return generator
.moveToDestinationIfNeeded(dst
, result
);
1265 // ------------------------------ ReadModifyBracketNode -----------------------------------
1267 RegisterID
* ReadModifyBracketNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1269 RefPtr
<RegisterID
> base
= generator
.emitNodeForLeftHandSide(m_base
, m_subscriptHasAssignments
|| m_rightHasAssignments
, m_subscript
->isPure(generator
) && m_right
->isPure(generator
));
1270 RefPtr
<RegisterID
> property
= generator
.emitNodeForLeftHandSide(m_subscript
, m_rightHasAssignments
, m_right
->isPure(generator
));
1272 generator
.emitExpressionInfo(divot() - m_subexpressionDivotOffset
, startOffset() - m_subexpressionDivotOffset
, m_subexpressionEndOffset
);
1273 RefPtr
<RegisterID
> value
= generator
.emitGetByVal(generator
.tempDestination(dst
), base
.get(), property
.get());
1274 RegisterID
* updatedValue
= emitReadModifyAssignment(generator
, generator
.finalDestination(dst
, value
.get()), value
.get(), m_right
, m_operator
, OperandTypes(ResultType::unknownType(), m_right
->resultDescriptor()));
1276 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1277 generator
.emitPutByVal(base
.get(), property
.get(), updatedValue
);
1279 return updatedValue
;
1282 // ------------------------------ CommaNode ------------------------------------
1284 RegisterID
* CommaNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1286 ASSERT(m_expressions
.size() > 1);
1287 for (size_t i
= 0; i
< m_expressions
.size() - 1; i
++)
1288 generator
.emitNode(generator
.ignoredResult(), m_expressions
[i
]);
1289 return generator
.emitNode(dst
, m_expressions
.last());
1292 // ------------------------------ ConstDeclNode ------------------------------------
1294 RegisterID
* ConstDeclNode::emitCodeSingle(BytecodeGenerator
& generator
)
1296 if (RegisterID
* local
= generator
.constRegisterFor(m_ident
)) {
1300 return generator
.emitNode(local
, m_init
);
1303 if (generator
.codeType() != EvalCode
) {
1305 return generator
.emitNode(m_init
);
1307 return generator
.emitResolve(generator
.newTemporary(), m_ident
);
1309 // FIXME: While this code should only be hit in eval code, it will potentially
1310 // assign to the wrong base if m_ident exists in an intervening dynamic scope.
1311 RefPtr
<RegisterID
> base
= generator
.emitResolveBase(generator
.newTemporary(), m_ident
);
1312 RegisterID
* value
= m_init
? generator
.emitNode(m_init
) : generator
.emitLoad(0, jsUndefined());
1313 return generator
.emitPutById(base
.get(), m_ident
, value
);
1316 RegisterID
* ConstDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1318 RegisterID
* result
= 0;
1319 for (ConstDeclNode
* n
= this; n
; n
= n
->m_next
)
1320 result
= n
->emitCodeSingle(generator
);
1325 // ------------------------------ ConstStatementNode -----------------------------
1327 RegisterID
* ConstStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1329 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1330 return generator
.emitNode(m_next
);
1333 // ------------------------------ SourceElements -------------------------------
1336 inline StatementNode
* SourceElements::lastStatement() const
1338 size_t size
= m_statements
.size();
1339 return size
? m_statements
[size
- 1] : 0;
1342 inline void SourceElements::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1344 size_t size
= m_statements
.size();
1345 for (size_t i
= 0; i
< size
; ++i
)
1346 generator
.emitNode(dst
, m_statements
[i
]);
1349 // ------------------------------ BlockNode ------------------------------------
1351 inline StatementNode
* BlockNode::lastStatement() const
1353 return m_statements
? m_statements
->lastStatement() : 0;
1356 inline StatementNode
* BlockNode::singleStatement() const
1358 return m_statements
? m_statements
->singleStatement() : 0;
1361 RegisterID
* BlockNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1364 m_statements
->emitBytecode(generator
, dst
);
1368 // ------------------------------ EmptyStatementNode ---------------------------
1370 RegisterID
* EmptyStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1372 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1376 // ------------------------------ DebuggerStatementNode ---------------------------
1378 RegisterID
* DebuggerStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1380 generator
.emitDebugHook(DidReachBreakpoint
, firstLine(), lastLine());
1384 // ------------------------------ ExprStatementNode ----------------------------
1386 RegisterID
* ExprStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1389 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1390 return generator
.emitNode(dst
, m_expr
);
1393 // ------------------------------ VarStatementNode ----------------------------
1395 RegisterID
* VarStatementNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1398 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1399 return generator
.emitNode(m_expr
);
1402 // ------------------------------ IfNode ---------------------------------------
1404 RegisterID
* IfNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1406 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1408 RefPtr
<Label
> afterThen
= generator
.newLabel();
1410 if (m_condition
->hasConditionContextCodegen()) {
1411 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1412 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), afterThen
.get(), true);
1413 generator
.emitLabel(beforeThen
.get());
1415 RegisterID
* cond
= generator
.emitNode(m_condition
);
1416 generator
.emitJumpIfFalse(cond
, afterThen
.get());
1419 generator
.emitNode(dst
, m_ifBlock
);
1420 generator
.emitLabel(afterThen
.get());
1422 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1426 // ------------------------------ IfElseNode ---------------------------------------
1428 RegisterID
* IfElseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1430 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1432 RefPtr
<Label
> beforeElse
= generator
.newLabel();
1433 RefPtr
<Label
> afterElse
= generator
.newLabel();
1435 if (m_condition
->hasConditionContextCodegen()) {
1436 RefPtr
<Label
> beforeThen
= generator
.newLabel();
1437 generator
.emitNodeInConditionContext(m_condition
, beforeThen
.get(), beforeElse
.get(), true);
1438 generator
.emitLabel(beforeThen
.get());
1440 RegisterID
* cond
= generator
.emitNode(m_condition
);
1441 generator
.emitJumpIfFalse(cond
, beforeElse
.get());
1444 generator
.emitNode(dst
, m_ifBlock
);
1445 generator
.emitJump(afterElse
.get());
1447 generator
.emitLabel(beforeElse
.get());
1449 generator
.emitNode(dst
, m_elseBlock
);
1451 generator
.emitLabel(afterElse
.get());
1453 // FIXME: This should return the last statement executed so that it can be returned as a Completion.
1457 // ------------------------------ DoWhileNode ----------------------------------
1459 RegisterID
* DoWhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1461 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1463 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1464 generator
.emitLabel(topOfLoop
.get());
1466 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1468 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1470 generator
.emitLabel(scope
->continueTarget());
1471 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1472 if (m_expr
->hasConditionContextCodegen())
1473 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1475 RegisterID
* cond
= generator
.emitNode(m_expr
);
1476 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1479 generator
.emitLabel(scope
->breakTarget());
1480 return result
.get();
1483 // ------------------------------ WhileNode ------------------------------------
1485 RegisterID
* WhileNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1487 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1489 generator
.emitJump(scope
->continueTarget());
1491 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1492 generator
.emitLabel(topOfLoop
.get());
1494 generator
.emitNode(dst
, m_statement
);
1496 generator
.emitLabel(scope
->continueTarget());
1497 generator
.emitDebugHook(WillExecuteStatement
, m_expr
->lineNo(), m_expr
->lineNo());
1499 if (m_expr
->hasConditionContextCodegen())
1500 generator
.emitNodeInConditionContext(m_expr
, topOfLoop
.get(), scope
->breakTarget(), false);
1502 RegisterID
* cond
= generator
.emitNode(m_expr
);
1503 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1506 generator
.emitLabel(scope
->breakTarget());
1508 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1512 // ------------------------------ ForNode --------------------------------------
1514 RegisterID
* ForNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1516 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1518 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1521 generator
.emitNode(generator
.ignoredResult(), m_expr1
);
1523 RefPtr
<Label
> condition
= generator
.newLabel();
1524 generator
.emitJump(condition
.get());
1526 RefPtr
<Label
> topOfLoop
= generator
.newLabel();
1527 generator
.emitLabel(topOfLoop
.get());
1529 RefPtr
<RegisterID
> result
= generator
.emitNode(dst
, m_statement
);
1531 generator
.emitLabel(scope
->continueTarget());
1532 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1534 generator
.emitNode(generator
.ignoredResult(), m_expr3
);
1536 generator
.emitLabel(condition
.get());
1538 if (m_expr2
->hasConditionContextCodegen())
1539 generator
.emitNodeInConditionContext(m_expr2
, topOfLoop
.get(), scope
->breakTarget(), false);
1541 RegisterID
* cond
= generator
.emitNode(m_expr2
);
1542 generator
.emitJumpIfTrue(cond
, topOfLoop
.get());
1545 generator
.emitJump(topOfLoop
.get());
1547 generator
.emitLabel(scope
->breakTarget());
1548 return result
.get();
1551 // ------------------------------ ForInNode ------------------------------------
1553 RegisterID
* ForInNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1555 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Loop
);
1557 if (!m_lexpr
->isLocation())
1558 return emitThrowReferenceError(generator
, "Left side of for-in statement is not a reference.");
1560 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1563 generator
.emitNode(generator
.ignoredResult(), m_init
);
1565 RefPtr
<RegisterID
> base
= generator
.newTemporary();
1566 generator
.emitNode(base
.get(), m_expr
);
1567 RefPtr
<RegisterID
> i
= generator
.newTemporary();
1568 RefPtr
<RegisterID
> size
= generator
.newTemporary();
1569 RefPtr
<RegisterID
> expectedSubscript
;
1570 RefPtr
<RegisterID
> iter
= generator
.emitGetPropertyNames(generator
.newTemporary(), base
.get(), i
.get(), size
.get(), scope
->breakTarget());
1571 generator
.emitJump(scope
->continueTarget());
1573 RefPtr
<Label
> loopStart
= generator
.newLabel();
1574 generator
.emitLabel(loopStart
.get());
1576 RegisterID
* propertyName
;
1577 bool optimizedForinAccess
= false;
1578 if (m_lexpr
->isResolveNode()) {
1579 const Identifier
& ident
= static_cast<ResolveNode
*>(m_lexpr
)->identifier();
1580 propertyName
= generator
.registerFor(ident
);
1581 if (!propertyName
) {
1582 propertyName
= generator
.newTemporary();
1583 RefPtr
<RegisterID
> protect
= propertyName
;
1584 RegisterID
* base
= generator
.emitResolveBaseForPut(generator
.newTemporary(), ident
);
1586 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1587 generator
.emitPutById(base
, ident
, propertyName
);
1589 expectedSubscript
= generator
.emitMove(generator
.newTemporary(), propertyName
);
1590 generator
.pushOptimisedForIn(expectedSubscript
.get(), iter
.get(), i
.get(), propertyName
);
1591 optimizedForinAccess
= true;
1593 } else if (m_lexpr
->isDotAccessorNode()) {
1594 DotAccessorNode
* assignNode
= static_cast<DotAccessorNode
*>(m_lexpr
);
1595 const Identifier
& ident
= assignNode
->identifier();
1596 propertyName
= generator
.newTemporary();
1597 RefPtr
<RegisterID
> protect
= propertyName
;
1598 RegisterID
* base
= generator
.emitNode(assignNode
->base());
1600 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1601 generator
.emitPutById(base
, ident
, propertyName
);
1603 ASSERT(m_lexpr
->isBracketAccessorNode());
1604 BracketAccessorNode
* assignNode
= static_cast<BracketAccessorNode
*>(m_lexpr
);
1605 propertyName
= generator
.newTemporary();
1606 RefPtr
<RegisterID
> protect
= propertyName
;
1607 RefPtr
<RegisterID
> base
= generator
.emitNode(assignNode
->base());
1608 RegisterID
* subscript
= generator
.emitNode(assignNode
->subscript());
1610 generator
.emitExpressionInfo(assignNode
->divot(), assignNode
->startOffset(), assignNode
->endOffset());
1611 generator
.emitPutByVal(base
.get(), subscript
, propertyName
);
1614 generator
.emitNode(dst
, m_statement
);
1616 if (optimizedForinAccess
)
1617 generator
.popOptimisedForIn();
1619 generator
.emitLabel(scope
->continueTarget());
1620 generator
.emitNextPropertyName(propertyName
, base
.get(), i
.get(), size
.get(), iter
.get(), loopStart
.get());
1621 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1622 generator
.emitLabel(scope
->breakTarget());
1626 // ------------------------------ ContinueNode ---------------------------------
1629 RegisterID
* ContinueNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1631 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1633 LabelScope
* scope
= generator
.continueTarget(m_ident
);
1636 generator
.emitJumpScopes(scope
->continueTarget(), scope
->scopeDepth());
1640 // ------------------------------ BreakNode ------------------------------------
1643 RegisterID
* BreakNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1645 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1647 LabelScope
* scope
= generator
.breakTarget(m_ident
);
1650 generator
.emitJumpScopes(scope
->breakTarget(), scope
->scopeDepth());
1654 // ------------------------------ ReturnNode -----------------------------------
1656 RegisterID
* ReturnNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1658 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1659 ASSERT(generator
.codeType() == FunctionCode
);
1661 if (dst
== generator
.ignoredResult())
1663 RegisterID
* r0
= m_value
? generator
.emitNode(dst
, m_value
) : generator
.emitLoad(dst
, jsUndefined());
1664 RefPtr
<RegisterID
> returnRegister
;
1665 if (generator
.scopeDepth()) {
1666 RefPtr
<Label
> l0
= generator
.newLabel();
1667 if (generator
.hasFinaliser() && !r0
->isTemporary()) {
1668 returnRegister
= generator
.emitMove(generator
.newTemporary(), r0
);
1669 r0
= returnRegister
.get();
1671 generator
.emitJumpScopes(l0
.get(), 0);
1672 generator
.emitLabel(l0
.get());
1674 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
1675 return generator
.emitReturn(r0
);
1678 // ------------------------------ WithNode -------------------------------------
1680 RegisterID
* WithNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1682 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1684 RefPtr
<RegisterID
> scope
= generator
.newTemporary();
1685 generator
.emitNode(scope
.get(), m_expr
); // scope must be protected until popped
1686 generator
.emitExpressionInfo(m_divot
, m_expressionLength
, 0);
1687 generator
.emitPushScope(scope
.get());
1688 RegisterID
* result
= generator
.emitNode(dst
, m_statement
);
1689 generator
.emitPopScope();
1693 // ------------------------------ CaseClauseNode --------------------------------
1695 inline void CaseClauseNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1698 m_statements
->emitBytecode(generator
, dst
);
1701 // ------------------------------ CaseBlockNode --------------------------------
1710 static void processClauseList(ClauseListNode
* list
, Vector
<ExpressionNode
*, 8>& literalVector
, SwitchKind
& typeForTable
, bool& singleCharacterSwitch
, int32_t& min_num
, int32_t& max_num
)
1712 for (; list
; list
= list
->getNext()) {
1713 ExpressionNode
* clauseExpression
= list
->getClause()->expr();
1714 literalVector
.append(clauseExpression
);
1715 if (clauseExpression
->isNumber()) {
1716 double value
= static_cast<NumberNode
*>(clauseExpression
)->value();
1717 int32_t intVal
= static_cast<int32_t>(value
);
1718 if ((typeForTable
& ~SwitchNumber
) || (intVal
!= value
)) {
1719 typeForTable
= SwitchNeither
;
1722 if (intVal
< min_num
)
1724 if (intVal
> max_num
)
1726 typeForTable
= SwitchNumber
;
1729 if (clauseExpression
->isString()) {
1730 if (typeForTable
& ~SwitchString
) {
1731 typeForTable
= SwitchNeither
;
1734 const UString
& value
= static_cast<StringNode
*>(clauseExpression
)->value().ustring();
1735 if (singleCharacterSwitch
&= value
.length() == 1) {
1736 int32_t intVal
= value
.impl()->characters()[0];
1737 if (intVal
< min_num
)
1739 if (intVal
> max_num
)
1742 typeForTable
= SwitchString
;
1745 typeForTable
= SwitchNeither
;
1750 SwitchInfo::SwitchType
CaseBlockNode::tryOptimizedSwitch(Vector
<ExpressionNode
*, 8>& literalVector
, int32_t& min_num
, int32_t& max_num
)
1752 SwitchKind typeForTable
= SwitchUnset
;
1753 bool singleCharacterSwitch
= true;
1755 processClauseList(m_list1
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1756 processClauseList(m_list2
, literalVector
, typeForTable
, singleCharacterSwitch
, min_num
, max_num
);
1758 if (typeForTable
== SwitchUnset
|| typeForTable
== SwitchNeither
)
1759 return SwitchInfo::SwitchNone
;
1761 if (typeForTable
== SwitchNumber
) {
1762 int32_t range
= max_num
- min_num
;
1763 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1764 return SwitchInfo::SwitchImmediate
;
1765 return SwitchInfo::SwitchNone
;
1768 ASSERT(typeForTable
== SwitchString
);
1770 if (singleCharacterSwitch
) {
1771 int32_t range
= max_num
- min_num
;
1772 if (min_num
<= max_num
&& range
<= 1000 && (range
/ literalVector
.size()) < 10)
1773 return SwitchInfo::SwitchCharacter
;
1776 return SwitchInfo::SwitchString
;
1779 RegisterID
* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator
& generator
, RegisterID
* switchExpression
, RegisterID
* dst
)
1781 RefPtr
<Label
> defaultLabel
;
1782 Vector
<RefPtr
<Label
>, 8> labelVector
;
1783 Vector
<ExpressionNode
*, 8> literalVector
;
1784 int32_t min_num
= std::numeric_limits
<int32_t>::max();
1785 int32_t max_num
= std::numeric_limits
<int32_t>::min();
1786 SwitchInfo::SwitchType switchType
= tryOptimizedSwitch(literalVector
, min_num
, max_num
);
1788 if (switchType
!= SwitchInfo::SwitchNone
) {
1789 // Prepare the various labels
1790 for (uint32_t i
= 0; i
< literalVector
.size(); i
++)
1791 labelVector
.append(generator
.newLabel());
1792 defaultLabel
= generator
.newLabel();
1793 generator
.beginSwitch(switchExpression
, switchType
);
1796 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1797 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1798 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1799 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1800 labelVector
.append(generator
.newLabel());
1801 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1804 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1805 RefPtr
<RegisterID
> clauseVal
= generator
.newTemporary();
1806 generator
.emitNode(clauseVal
.get(), list
->getClause()->expr());
1807 generator
.emitBinaryOp(op_stricteq
, clauseVal
.get(), clauseVal
.get(), switchExpression
, OperandTypes());
1808 labelVector
.append(generator
.newLabel());
1809 generator
.emitJumpIfTrue(clauseVal
.get(), labelVector
[labelVector
.size() - 1].get());
1811 defaultLabel
= generator
.newLabel();
1812 generator
.emitJump(defaultLabel
.get());
1815 RegisterID
* result
= 0;
1818 for (ClauseListNode
* list
= m_list1
; list
; list
= list
->getNext()) {
1819 generator
.emitLabel(labelVector
[i
++].get());
1820 list
->getClause()->emitBytecode(generator
, dst
);
1823 if (m_defaultClause
) {
1824 generator
.emitLabel(defaultLabel
.get());
1825 m_defaultClause
->emitBytecode(generator
, dst
);
1828 for (ClauseListNode
* list
= m_list2
; list
; list
= list
->getNext()) {
1829 generator
.emitLabel(labelVector
[i
++].get());
1830 list
->getClause()->emitBytecode(generator
, dst
);
1832 if (!m_defaultClause
)
1833 generator
.emitLabel(defaultLabel
.get());
1835 ASSERT(i
== labelVector
.size());
1836 if (switchType
!= SwitchInfo::SwitchNone
) {
1837 ASSERT(labelVector
.size() == literalVector
.size());
1838 generator
.endSwitch(labelVector
.size(), labelVector
.data(), literalVector
.data(), defaultLabel
.get(), min_num
, max_num
);
1843 // ------------------------------ SwitchNode -----------------------------------
1845 RegisterID
* SwitchNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1847 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1849 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::Switch
);
1851 RefPtr
<RegisterID
> r0
= generator
.emitNode(m_expr
);
1852 RegisterID
* r1
= m_block
->emitBytecodeForBlock(generator
, r0
.get(), dst
);
1854 generator
.emitLabel(scope
->breakTarget());
1858 // ------------------------------ LabelNode ------------------------------------
1860 RegisterID
* LabelNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1862 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1864 ASSERT(!generator
.breakTarget(m_name
));
1866 RefPtr
<LabelScope
> scope
= generator
.newLabelScope(LabelScope::NamedLabel
, &m_name
);
1867 RegisterID
* r0
= generator
.emitNode(dst
, m_statement
);
1869 generator
.emitLabel(scope
->breakTarget());
1873 // ------------------------------ ThrowNode ------------------------------------
1875 RegisterID
* ThrowNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1877 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1879 if (dst
== generator
.ignoredResult())
1881 RefPtr
<RegisterID
> expr
= generator
.emitNode(m_expr
);
1882 generator
.emitExpressionInfo(divot(), startOffset(), endOffset());
1883 generator
.emitThrow(expr
.get());
1887 // ------------------------------ TryNode --------------------------------------
1889 RegisterID
* TryNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1891 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1892 // optimizer knows they may be jumped to from anywhere.
1894 generator
.emitDebugHook(WillExecuteStatement
, firstLine(), lastLine());
1896 RefPtr
<Label
> tryStartLabel
= generator
.newLabel();
1897 RefPtr
<Label
> finallyStart
;
1898 RefPtr
<RegisterID
> finallyReturnAddr
;
1899 if (m_finallyBlock
) {
1900 finallyStart
= generator
.newLabel();
1901 finallyReturnAddr
= generator
.newTemporary();
1902 generator
.pushFinallyContext(finallyStart
.get(), finallyReturnAddr
.get());
1905 generator
.emitLabel(tryStartLabel
.get());
1906 generator
.emitNode(dst
, m_tryBlock
);
1909 RefPtr
<Label
> catchEndLabel
= generator
.newLabel();
1911 // Normal path: jump over the catch block.
1912 generator
.emitJump(catchEndLabel
.get());
1914 // Uncaught exception path: the catch block.
1915 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1916 RefPtr
<RegisterID
> exceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1917 if (m_catchHasEval
) {
1918 RefPtr
<RegisterID
> dynamicScopeObject
= generator
.emitNewObject(generator
.newTemporary());
1919 generator
.emitPutById(dynamicScopeObject
.get(), m_exceptionIdent
, exceptionRegister
.get());
1920 generator
.emitMove(exceptionRegister
.get(), dynamicScopeObject
.get());
1921 generator
.emitPushScope(exceptionRegister
.get());
1923 generator
.emitPushNewScope(exceptionRegister
.get(), m_exceptionIdent
, exceptionRegister
.get());
1924 generator
.emitNode(dst
, m_catchBlock
);
1925 generator
.emitPopScope();
1926 generator
.emitLabel(catchEndLabel
.get());
1929 if (m_finallyBlock
) {
1930 generator
.popFinallyContext();
1931 // there may be important registers live at the time we jump
1932 // to a finally block (such as for a return or throw) so we
1933 // ref the highest register ever used as a conservative
1934 // approach to not clobbering anything important
1935 RefPtr
<RegisterID
> highestUsedRegister
= generator
.highestUsedRegister();
1936 RefPtr
<Label
> finallyEndLabel
= generator
.newLabel();
1938 // Normal path: invoke the finally block, then jump over it.
1939 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1940 generator
.emitJump(finallyEndLabel
.get());
1942 // Uncaught exception path: invoke the finally block, then re-throw the exception.
1943 RefPtr
<Label
> here
= generator
.emitLabel(generator
.newLabel().get());
1944 RefPtr
<RegisterID
> tempExceptionRegister
= generator
.emitCatch(generator
.newTemporary(), tryStartLabel
.get(), here
.get());
1945 generator
.emitJumpSubroutine(finallyReturnAddr
.get(), finallyStart
.get());
1946 generator
.emitThrow(tempExceptionRegister
.get());
1948 // The finally block.
1949 generator
.emitLabel(finallyStart
.get());
1950 generator
.emitNode(dst
, m_finallyBlock
);
1951 generator
.emitSubroutineReturn(finallyReturnAddr
.get());
1953 generator
.emitLabel(finallyEndLabel
.get());
1959 // ------------------------------ ScopeNode -----------------------------
1961 inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
1963 if (m_data
->m_statements
)
1964 m_data
->m_statements
->emitBytecode(generator
, dst
);
1967 // ------------------------------ ProgramNode -----------------------------
1969 RegisterID
* ProgramNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1971 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1973 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1974 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1975 emitStatementsBytecode(generator
, dstRegister
.get());
1977 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1978 generator
.emitEnd(dstRegister
.get());
1982 // ------------------------------ EvalNode -----------------------------
1984 RegisterID
* EvalNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
1986 generator
.emitDebugHook(WillExecuteProgram
, firstLine(), lastLine());
1988 RefPtr
<RegisterID
> dstRegister
= generator
.newTemporary();
1989 generator
.emitLoad(dstRegister
.get(), jsUndefined());
1990 emitStatementsBytecode(generator
, dstRegister
.get());
1992 generator
.emitDebugHook(DidExecuteProgram
, firstLine(), lastLine());
1993 generator
.emitEnd(dstRegister
.get());
1997 // ------------------------------ FunctionBodyNode -----------------------------
1999 RegisterID
* FunctionBodyNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
*)
2001 generator
.emitDebugHook(DidEnterCallFrame
, firstLine(), lastLine());
2002 emitStatementsBytecode(generator
, generator
.ignoredResult());
2004 StatementNode
* singleStatement
= this->singleStatement();
2005 ReturnNode
* returnNode
= 0;
2007 // Check for a return statement at the end of a function composed of a single block.
2008 if (singleStatement
&& singleStatement
->isBlock()) {
2009 StatementNode
* lastStatementInBlock
= static_cast<BlockNode
*>(singleStatement
)->lastStatement();
2010 if (lastStatementInBlock
&& lastStatementInBlock
->isReturnNode())
2011 returnNode
= static_cast<ReturnNode
*>(lastStatementInBlock
);
2014 // If there is no return we must automatically insert one.
2016 RegisterID
* r0
= generator
.isConstructor() ? generator
.thisRegister() : generator
.emitLoad(0, jsUndefined());
2017 generator
.emitDebugHook(WillLeaveCallFrame
, firstLine(), lastLine());
2018 generator
.emitReturn(r0
);
2022 // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
2023 if (static_cast<BlockNode
*>(singleStatement
)->singleStatement()) {
2024 ExpressionNode
* returnValueExpression
= returnNode
->value();
2025 if (returnValueExpression
&& returnValueExpression
->isSubtract()) {
2026 ExpressionNode
* lhsExpression
= static_cast<SubNode
*>(returnValueExpression
)->lhs();
2027 ExpressionNode
* rhsExpression
= static_cast<SubNode
*>(returnValueExpression
)->rhs();
2028 if (lhsExpression
->isResolveNode() && rhsExpression
->isResolveNode()) {
2029 generator
.setIsNumericCompareFunction(generator
.argumentNumberFor(static_cast<ResolveNode
*>(lhsExpression
)->identifier()) == 1
2030 && generator
.argumentNumberFor(static_cast<ResolveNode
*>(rhsExpression
)->identifier()) == 2);
2038 // ------------------------------ FuncDeclNode ---------------------------------
2040 RegisterID
* FuncDeclNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2042 if (dst
== generator
.ignoredResult())
2047 // ------------------------------ FuncExprNode ---------------------------------
2049 RegisterID
* FuncExprNode::emitBytecode(BytecodeGenerator
& generator
, RegisterID
* dst
)
2051 return generator
.emitNewFunctionExpression(generator
.finalDestination(dst
), this);