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

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

2009-05-12 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Add SamplingCounter tool to provide a simple mechanism for counting events in JSC
(enabled using ENABLE(SAMPLING_COUNTERS)). To count events within a single function
use the class 'SamplingCounter', where the counter may be incremented from multiple
functions 'GlobalSamplingCounter' may be convenient; all other counters (stack or
heap allocated, rather than statically declared) should use the DeletableSamplingCounter.
Further description of these classes is provided alongside their definition in
SamplingTool.h.

Counters may be incremented from c++ by calling the 'count()' method on the counter,
or may be incremented by JIT code by using the 'emitCount()' method within the JIT.

This patch also fixes CODEBLOCK_SAMPLING, which was missing a null pointer check.

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