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

Last change on this file since 47667 was 47667, checked in by Darin Adler, 16 years ago

Fix Qt build.

Patch by Darin Adler <Darin Adler> on 2009-08-21

  • parser/Nodes.cpp:

(JSC::ScopeNodeData::ScopeNodeData): Made non-inline again.
This is used outside Nodes.cpp so can't be inline unless
it is in the header.

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