source: webkit/trunk/JavaScriptCore/bytecompiler/NodesCodegen.cpp@ 51882

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

move code generation portions of Nodes.cpp to bytecompiler directory
https://bugs.webkit.org/show_bug.cgi?id=32284

Reviewed by Darin Adler.

  • bytecompiler/NodesCodegen.cpp: Copied from parser/Nodes.cpp. Removed parts that

are not about codegen.

  • parser/Nodes.cpp: Removed everything that is about codegen.

Update build systems:

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