source: webkit/trunk/JavaScriptCore/parser/Nodes.cpp@ 51735

Last change on this file since 51735 was 51735, checked in by [email protected], 15 years ago

2009-12-05 Maciej Stachowiak <[email protected]>

Reviewed by Oliver Hunt.

conway benchmark spends half it's time in op_less (jump fusion fails)
https://bugs.webkit.org/show_bug.cgi?id=32190

<1% speedup on SunSpider and V8
2x speedup on "conway" benchmark


Two optimizations:

1) Improve codegen for logical operators &&,
and ! in a condition context


When generating code for combinations of &&,
and !, in a

condition context (i.e. in an if statement or loop condition), we
used to produce a value, and then separately jump based on its
truthiness. Now we pass the false and true targets in, and let the
logical operators generate jumps directly. This helps in four
ways:

a) Individual clauses of a short-circuit logical operator can now
jump directly to the then or else clause of an if statement (or to
the top or exit of a loop) instead of jumping to a jump.


b) It used to be that jump fusion with the condition of the first
clause of a logical operator was inhibited, because the register
was ref'd to be used later, in the actual condition jump; this no
longer happens since a jump straight to the final target is
generated directly.

c) It used to be that jump fusion with the condition of the second
clause of a logical operator was inhibited, because there was a
jump target right after the second clause and before the actual
condition jump. But now it's no longer necessary for the first
clause to jump there so jump fusion is not blocked.

d) We avoid generating excess mov statements in some cases.


As a concrete example this source:


if (!((x < q && y < q)
(t < q && z < q))) {

...

}


Used to generate this bytecode:


[ 34] less r1, r-15, r-19
[ 38] jfalse r1, 7(->45)
[ 41] less r1, r-16, r-19
[ 45] jtrue r1, 14(->59)
[ 48] less r1, r-17, r-19
[ 52] jfalse r1, 7(->59)
[ 55] less r1, r-18, r-19
[ 59] jtrue r1, 17(->76)


And now generates this bytecode (also taking advantage of the second optimization below):


[ 34] jnless r-15, r-19, 8(->42)
[ 38] jless r-16, r-19, 26(->64)
[ 42] jnless r-17, r-19, 8(->50)
[ 46] jless r-18, r-19, 18(->64)


Note the jump fusion and the fact that there's less jump
indirection - three of the four jumps go straight to the target
clause instead of indirecting through another jump.


2) Implement jless opcode to take advantage of the above, since we'll now often generate
a less followed by a jtrue where fusion is not forbidden.


  • parser/Nodes.h: (JSC::ExpressionNode::hasConditionContextCodegen): Helper function to determine whether a node supports special conditional codegen. Return false as this is the default. (JSC::ExpressionNode::emitBytecodeInConditionContext): Assert not reached - only really defined for nodes that do have conditional codegen. (JSC::UnaryOpNode::expr): Add const version. (JSC::LogicalNotNode::hasConditionContextCodegen): Returne true only if subexpression supports it. (JSC::LogicalOpNode::hasConditionContextCodegen): Return true.
  • parser/Nodes.cpp: (JSC::LogicalNotNode::emitBytecodeInConditionContext): Implemented - just swap the true and false targets for the child node. (JSC::LogicalOpNode::emitBytecodeInConditionContext): Implemented - handle jumps directly, improving codegen quality. Also handles further nested conditional codegen. (JSC::ConditionalNode::emitBytecode): Use condition context codegen when available. (JSC::IfNode::emitBytecode): ditto (JSC::IfElseNode::emitBytecode): ditto (JSC::DoWhileNode::emitBytecode): ditto (JSC::WhileNode::emitBytecode): ditto (JSC::ForNode::emitBytecode): ditto
  • bytecode/Opcode.h:
  • Added loop_if_false opcode - needed now that falsey jumps can be backwards.
  • Added jless opcode to take advantage of new fusion opportunities.
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): Handle above.
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitJumpIfTrue): Add peephole for less + jtrue ==> jless. (JSC::BytecodeGenerator::emitJumpIfFalse): Add handling of backwrds falsey jumps.
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::emitNodeInConditionContext): Wrapper to handle tracking of overly deep expressions etc.
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute): Implement the two new opcodes (loop_if_false, jless).
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): Implement JIT support for the two new opcodes. (JSC::JIT::privateCompileSlowCases): ditto
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::emit_op_jless): (JSC::JIT::emitSlow_op_jless): ditto (JSC::JIT::emitBinaryDoubleOp): ditto
  • jit/JITOpcodes.cpp: (JSC::JIT::emitSlow_op_loop_if_less): ditto (JSC::JIT::emit_op_loop_if_false): ditto (JSC::JIT::emitSlow_op_loop_if_false): ditto
  • jit/JITStubs.cpp:
  • jit/JITStubs.h: (JSC::):

2009-12-05 Maciej Stachowiak <[email protected]>

Reviewed by Oliver Hunt.

conway benchmark spends half it's time in op_less (jump fusion fails)
https://bugs.webkit.org/show_bug.cgi?id=32190

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