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

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

Bug 26532: Native functions do not correctly unlink from optimised callsites when they're collected
<https://bugs.webkit.org/show_bug.cgi?id=26532> <rdar://problem/6625385>

Reviewed by Gavin "Viceroy of Venezuela" Barraclough.

We need to make sure that each native function instance correctly unlinks any references to it
when it is collected. Allowing this to happen required a few changes:

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