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

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

JavaScriptCore:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Sam Weinig.

Stop loading constants into the register file.

Instead, use high register values (highest bit bar the sign bit set) to indicate
constants in the instruction stream, and when we encounter such a value load it
directly from the CodeBlock.

Since constants are no longer copied into the register file, this patch renders
the 'unexpected constant' mechanism redundant, and removes it.

2% improvement, thanks to Sam Weinig.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::mark): (JSC::CodeBlock::shrinkToFit):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::isTemporaryRegisterIndex): (JSC::CodeBlock::constantRegister): (JSC::CodeBlock::isConstantRegisterIndex): (JSC::CodeBlock::getConstant): (JSC::ExecState::r):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::preserveLastVar): (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::addConstantValue): (JSC::BytecodeGenerator::emitEqualityOp): (JSC::BytecodeGenerator::emitLoad): (JSC::BytecodeGenerator::emitResolveBase): (JSC::BytecodeGenerator::emitResolveWithBase): (JSC::BytecodeGenerator::emitNewError):
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::emitNode):
  • interpreter/CallFrame.h: (JSC::ExecState::noCaller): (JSC::ExecState::hasHostCallFrameFlag): (JSC::ExecState::addHostCallFrameFlag): (JSC::ExecState::removeHostCallFrameFlag):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::resolve): (JSC::Interpreter::resolveSkip): (JSC::Interpreter::resolveGlobal): (JSC::Interpreter::resolveBase): (JSC::Interpreter::resolveBaseAndProperty): (JSC::Interpreter::resolveBaseAndFunc): (JSC::Interpreter::dumpRegisters): (JSC::Interpreter::throwException): (JSC::Interpreter::createExceptionScope): (JSC::Interpreter::privateExecute): (JSC::Interpreter::retrieveArguments):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JITInlineMethods.h: (JSC::JIT::emitLoadDouble): (JSC::JIT::emitLoadInt32ToDouble):
  • jit/JITOpcodes.cpp: (JSC::JIT::emit_op_new_error): (JSC::JIT::emit_op_enter): (JSC::JIT::emit_op_enter_with_activation):
  • parser/Nodes.cpp: (JSC::DeleteResolveNode::emitBytecode): (JSC::DeleteValueNode::emitBytecode): (JSC::PrefixResolveNode::emitBytecode):
  • runtime/JSActivation.cpp: (JSC::JSActivation::JSActivation):
  • wtf/Platform.h:

LayoutTests:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

fast/js/global-recursion-on-full-stack.html is a little finicky.

The test recurses down the JS stack to find the bottom (catching this with an exception),
then tries to call a host function (document.write), switch writes new '<script>' code,
and expects this code to be run, then expects this code to try to call 'f();' again,
which it expects to fail, and it expects to catch that exception. However it is possible
that one of the earlier stages (the call to document.write, entering the interpreter to
run the new global code) will fail, depending on exactly how much stack space was free at
the point the last call to f() failed.

Tweak the test to make it work.

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