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