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