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
48using namespace WTF;
49
50namespace JSC {
51
52/*
53 Details of the emitBytecode function.
54
55 Return value: The register holding the production's value.
56 dst: An optional parameter specifying the most efficient destination at
57 which to store the production's value. The callee must honor dst.
58
59 The dst argument provides for a crude form of copy propagation. For example,
60
61 x = 1
62
63 becomes
64
65 load r[x], 1
66
67 instead of
68
69 load r0, 1
70 mov r[x], r0
71
72 because the assignment node, "x =", passes r[x] as dst to the number node, "1".
73*/
74
75// ------------------------------ ThrowableExpressionData --------------------------------
76
77static void substitute(UString& string, const UString& substring)
78{
79 int position = string.find(f: "%s");
80 ASSERT(position != -1);
81 string = makeString(string1: string.substr(pos: 0, len: position), string2: substring, string3: string.substr(pos: position + 2));
82}
83
84RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message)
85{
86 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
87 RegisterID* exception = generator.emitNewError(dst: generator.newTemporary(), type, message: jsString(globalData: generator.globalData(), s: message));
88 generator.emitThrow(exc: exception);
89 return exception;
90}
91
92RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label)
93{
94 UString message = messageTemplate;
95 substitute(string&: message, substring: label);
96 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
97 RegisterID* exception = generator.emitNewError(dst: generator.newTemporary(), type, message: jsString(globalData: generator.globalData(), s: message));
98 generator.emitThrow(exc: exception);
99 return exception;
100}
101
102inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label)
103{
104 return emitThrowError(generator, type, messageTemplate, label: label.ustring());
105}
106
107// ------------------------------ NullNode -------------------------------------
108
109RegisterID* 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
118RegisterID* 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
127RegisterID* 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
136RegisterID* 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
145RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
146{
147 RefPtr<RegExp> regExp = RegExp::create(globalData: generator.globalData(), pattern: m_pattern.ustring(), flags: m_flags.ustring());
148 if (!regExp->isValid())
149 return emitThrowError(generator, type: SyntaxError, messageTemplate: "Invalid regular expression: %s", label: regExp->errorMessage());
150 if (dst == generator.ignoredResult())
151 return 0;
152 return generator.emitNewRegExp(dst: generator.finalDestination(originalDst: dst), regExp: regExp.get());
153}
154
155// ------------------------------ ThisNode -------------------------------------
156
157RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
158{
159 if (dst == generator.ignoredResult())
160 return 0;
161 return generator.moveToDestinationIfNeeded(dst, src: generator.thisRegister());
162}
163
164// ------------------------------ ResolveNode ----------------------------------
165
166bool ResolveNode::isPure(BytecodeGenerator& generator) const
167{
168 return generator.isLocal(m_ident);
169}
170
171RegisterID* 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, src: local);
177 }
178
179 generator.emitExpressionInfo(divot: m_startOffset + m_ident.size(), startOffset: m_ident.size(), endOffset: 0);
180 return generator.emitResolve(dst: generator.finalDestination(originalDst: dst), property: m_ident);
181}
182
183// ------------------------------ ArrayNode ------------------------------------
184
185RegisterID* 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(dst: generator.finalDestination(originalDst: dst), m_element);
199
200 RefPtr<RegisterID> array = generator.emitNewArray(dst: generator.tempDestination(dst), m_element);
201
202 for (ElementNode* n = firstPutElement; n; n = n->next()) {
203 RegisterID* value = generator.emitNode(n: n->value());
204 length += n->elision();
205 generator.emitPutByIndex(base: array.get(), index: length++, value);
206 }
207
208 if (m_elision) {
209 RegisterID* value = generator.emitLoad(dst: 0, jsNumber(globalData: generator.globalData(), i: m_elision + length));
210 generator.emitPutById(base: array.get(), property: generator.propertyNames().length, value);
211 }
212
213 return generator.moveToDestinationIfNeeded(dst, src: array.get());
214}
215
216bool 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
227ArgumentListNode* 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
245RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
246{
247 if (!m_list) {
248 if (dst == generator.ignoredResult())
249 return 0;
250 return generator.emitNewObject(dst: generator.finalDestination(originalDst: dst));
251 }
252 return generator.emitNode(dst, n: m_list);
253}
254
255// ------------------------------ PropertyListNode -----------------------------
256
257RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
258{
259 RefPtr<RegisterID> newObj = generator.tempDestination(dst);
260
261 generator.emitNewObject(dst: newObj.get());
262
263 for (PropertyListNode* p = this; p; p = p->m_next) {
264 RegisterID* value = generator.emitNode(n: p->m_node->m_assign);
265
266 switch (p->m_node->m_type) {
267 case PropertyNode::Constant: {
268 generator.emitPutById(base: newObj.get(), property: p->m_node->name(), value);
269 break;
270 }
271 case PropertyNode::Getter: {
272 generator.emitPutGetter(base: newObj.get(), property: p->m_node->name(), value);
273 break;
274 }
275 case PropertyNode::Setter: {
276 generator.emitPutSetter(base: newObj.get(), property: p->m_node->name(), value);
277 break;
278 }
279 default:
280 ASSERT_NOT_REACHED();
281 }
282 }
283
284 return generator.moveToDestinationIfNeeded(dst, src: newObj.get());
285}
286
287// ------------------------------ BracketAccessorNode --------------------------------
288
289RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
290{
291 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(n: m_base, rightHasAssignments: m_subscriptHasAssignments, rightIsPure: m_subscript->isPure(generator));
292 RegisterID* property = generator.emitNode(n: m_subscript);
293 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
294 return generator.emitGetByVal(dst: generator.finalDestination(originalDst: dst), base: base.get(), property);
295}
296
297// ------------------------------ DotAccessorNode --------------------------------
298
299RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
300{
301 RegisterID* base = generator.emitNode(n: m_base);
302 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
303 return generator.emitGetById(dst: generator.finalDestination(originalDst: dst), base, property: m_ident);
304}
305
306// ------------------------------ ArgumentListNode -----------------------------
307
308RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
309{
310 ASSERT(m_expr);
311 return generator.emitNode(dst, n: m_expr);
312}
313
314// ------------------------------ NewExprNode ----------------------------------
315
316RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
317{
318 RefPtr<RegisterID> func = generator.emitNode(n: m_expr);
319 return generator.emitConstruct(dst: generator.finalDestination(originalDst: dst), func: func.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
320}
321
322// ------------------------------ EvalFunctionCallNode ----------------------------------
323
324RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
325{
326 RefPtr<RegisterID> func = generator.tempDestination(dst);
327 RefPtr<RegisterID> thisRegister = generator.newTemporary();
328 generator.emitExpressionInfo(divot: divot() - startOffset() + 4, startOffset: 4, endOffset: 0);
329 generator.emitResolveWithBase(baseDst: thisRegister.get(), propDst: func.get(), property: generator.propertyNames().eval);
330 return generator.emitCallEval(dst: generator.finalDestination(originalDst: dst, tempDst: func.get()), func: func.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
331}
332
333// ------------------------------ FunctionCallValueNode ----------------------------------
334
335RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
336{
337 RefPtr<RegisterID> func = generator.emitNode(n: m_expr);
338 RefPtr<RegisterID> thisRegister = generator.emitLoad(dst: generator.newTemporary(), jsNull());
339 return generator.emitCall(dst: generator.finalDestination(originalDst: dst, tempDst: func.get()), func: func.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
340}
341
342// ------------------------------ FunctionCallResolveNode ----------------------------------
343
344RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
345{
346 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
347 RefPtr<RegisterID> thisRegister = generator.emitLoad(dst: generator.newTemporary(), jsNull());
348 return generator.emitCall(dst: generator.finalDestination(originalDst: dst, tempDst: thisRegister.get()), func: local.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
349 }
350
351 int index = 0;
352 size_t depth = 0;
353 JSObject* globalObject = 0;
354 if (generator.findScopedProperty(m_ident, index, depth, forWriting: false, globalObject) && index != missingSymbolMarker()) {
355 RefPtr<RegisterID> func = generator.emitGetScopedVar(dst: generator.newTemporary(), skip: depth, index, globalObject);
356 RefPtr<RegisterID> thisRegister = generator.emitLoad(dst: generator.newTemporary(), jsNull());
357 return generator.emitCall(dst: generator.finalDestination(originalDst: dst, tempDst: func.get()), func: func.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
358 }
359
360 RefPtr<RegisterID> func = generator.newTemporary();
361 RefPtr<RegisterID> thisRegister = generator.newTemporary();
362 int identifierStart = divot() - startOffset();
363 generator.emitExpressionInfo(divot: identifierStart + m_ident.size(), startOffset: m_ident.size(), endOffset: 0);
364 generator.emitResolveWithBase(baseDst: thisRegister.get(), propDst: func.get(), property: m_ident);
365 return generator.emitCall(dst: generator.finalDestination(originalDst: dst, tempDst: func.get()), func: func.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
366}
367
368// ------------------------------ FunctionCallBracketNode ----------------------------------
369
370RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
371{
372 RefPtr<RegisterID> base = generator.emitNode(n: m_base);
373 RegisterID* property = generator.emitNode(n: m_subscript);
374 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
375 RefPtr<RegisterID> function = generator.emitGetByVal(dst: generator.tempDestination(dst), base: base.get(), property);
376 RefPtr<RegisterID> thisRegister = generator.emitMove(dst: generator.newTemporary(), src: base.get());
377 return generator.emitCall(dst: generator.finalDestination(originalDst: dst, tempDst: function.get()), func: function.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
378}
379
380// ------------------------------ FunctionCallDotNode ----------------------------------
381
382RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
383{
384 RefPtr<RegisterID> function = generator.tempDestination(dst);
385 RefPtr<RegisterID> thisRegister = generator.newTemporary();
386 generator.emitNode(dst: thisRegister.get(), n: m_base);
387 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
388 generator.emitMethodCheck();
389 generator.emitGetById(dst: function.get(), base: thisRegister.get(), property: m_ident);
390 return generator.emitCall(dst: generator.finalDestination(originalDst: dst, tempDst: function.get()), func: function.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
391}
392
393RegisterID* 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(n: m_base);
398 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
399 RefPtr<RegisterID> function = generator.emitGetById(dst: generator.tempDestination(dst), base: base.get(), property: m_ident);
400 RefPtr<RegisterID> finalDestination = generator.finalDestination(originalDst: dst, tempDst: function.get());
401 generator.emitJumpIfNotFunctionCall(cond: function.get(), target: realCall.get());
402 {
403 RefPtr<RegisterID> realFunction = generator.emitMove(dst: generator.tempDestination(dst), src: 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(dst: thisRegister.get(), n: m_args->m_listNode->m_expr);
408 m_args->m_listNode = m_args->m_listNode->m_next;
409 } else
410 generator.emitLoad(dst: thisRegister.get(), jsNull());
411
412 generator.emitCall(dst: finalDestination.get(), func: realFunction.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
413 generator.emitJump(target: end.get());
414 m_args->m_listNode = oldList;
415 }
416 generator.emitLabel(realCall.get());
417 {
418 RefPtr<RegisterID> thisRegister = generator.emitMove(dst: generator.newTemporary(), src: base.get());
419 generator.emitCall(dst: finalDestination.get(), func: function.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
420 }
421 generator.emitLabel(end.get());
422 return finalDestination.get();
423}
424
425static 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
431RegisterID* 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(args: m_args);
437
438 RefPtr<Label> realCall = generator.newLabel();
439 RefPtr<Label> end = generator.newLabel();
440 RefPtr<RegisterID> base = generator.emitNode(n: m_base);
441 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
442 RefPtr<RegisterID> function = generator.emitGetById(dst: generator.tempDestination(dst), base: base.get(), property: m_ident);
443 RefPtr<RegisterID> finalDestination = generator.finalDestination(originalDst: dst, tempDst: function.get());
444 generator.emitJumpIfNotFunctionApply(cond: function.get(), target: realCall.get());
445 {
446 if (mayBeCall) {
447 RefPtr<RegisterID> realFunction = generator.emitMove(dst: generator.tempDestination(dst), src: 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(dst: thisRegister.get(), n: 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(globalData: generator.globalData());
457 }
458 } else
459 generator.emitLoad(dst: thisRegister.get(), jsNull());
460 generator.emitCall(dst: finalDestination.get(), func: realFunction.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: 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(dst: generator.newTemporary(), src: base.get());
465 RefPtr<RegisterID> argsCountRegister = generator.newTemporary();
466 RefPtr<RegisterID> thisRegister = generator.newTemporary();
467 RefPtr<RegisterID> argsRegister = generator.newTemporary();
468 generator.emitNode(dst: thisRegister.get(), n: 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(dst: argsRegister.get(), src: generator.uncheckedRegisterForArguments());
476 }
477 if (!isArgumentsApply)
478 generator.emitNode(dst: argsRegister.get(), n: args->m_expr);
479 while ((args = args->m_next))
480 generator.emitNode(n: args->m_expr);
481
482 generator.emitLoadVarargs(argCountDst: argsCountRegister.get(), args: argsRegister.get());
483 generator.emitCallVarargs(dst: finalDestination.get(), func: realFunction.get(), thisRegister: thisRegister.get(), argCount: argsCountRegister.get(), divot: divot(), startOffset: startOffset(), endOffset: endOffset());
484 }
485 generator.emitJump(target: end.get());
486 }
487 generator.emitLabel(realCall.get());
488 {
489 RefPtr<RegisterID> thisRegister = generator.emitMove(dst: generator.newTemporary(), src: base.get());
490 generator.emitCall(dst: finalDestination.get(), func: function.get(), thisRegister: thisRegister.get(), m_args, divot: divot(), startOffset: startOffset(), endOffset: endOffset());
491 }
492 generator.emitLabel(end.get());
493 return finalDestination.get();
494}
495
496// ------------------------------ PostfixResolveNode ----------------------------------
497
498static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper)
499{
500 return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst);
501}
502
503static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper)
504{
505 if (srcDst == dst)
506 return generator.emitToJSNumber(dst, src: srcDst);
507 return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst);
508}
509
510RegisterID* 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(dst: generator.finalDestination(originalDst: dst), src: local);
517 }
518
519 if (dst == generator.ignoredResult())
520 return emitPreIncOrDec(generator, srcDst: local, oper: m_operator);
521 return emitPostIncOrDec(generator, dst: generator.finalDestination(originalDst: dst), srcDst: local, oper: 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, forWriting: true, globalObject) && index != missingSymbolMarker()) {
528 RefPtr<RegisterID> value = generator.emitGetScopedVar(dst: generator.newTemporary(), skip: depth, index, globalObject);
529 RegisterID* oldValue;
530 if (dst == generator.ignoredResult()) {
531 oldValue = 0;
532 emitPreIncOrDec(generator, srcDst: value.get(), oper: m_operator);
533 } else {
534 oldValue = emitPostIncOrDec(generator, dst: generator.finalDestination(originalDst: dst), srcDst: value.get(), oper: m_operator);
535 }
536 generator.emitPutScopedVar(skip: depth, index, value: value.get(), globalObject);
537 return oldValue;
538 }
539
540 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
541 RefPtr<RegisterID> value = generator.newTemporary();
542 RefPtr<RegisterID> base = generator.emitResolveWithBase(baseDst: generator.newTemporary(), propDst: value.get(), property: m_ident);
543 RegisterID* oldValue;
544 if (dst == generator.ignoredResult()) {
545 oldValue = 0;
546 emitPreIncOrDec(generator, srcDst: value.get(), oper: m_operator);
547 } else {
548 oldValue = emitPostIncOrDec(generator, dst: generator.finalDestination(originalDst: dst), srcDst: value.get(), oper: m_operator);
549 }
550 generator.emitPutById(base: base.get(), property: m_ident, value: value.get());
551 return oldValue;
552}
553
554// ------------------------------ PostfixBracketNode ----------------------------------
555
556RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
557{
558 RefPtr<RegisterID> base = generator.emitNode(n: m_base);
559 RefPtr<RegisterID> property = generator.emitNode(n: m_subscript);
560
561 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
562 RefPtr<RegisterID> value = generator.emitGetByVal(dst: generator.newTemporary(), base: base.get(), property: property.get());
563 RegisterID* oldValue;
564 if (dst == generator.ignoredResult()) {
565 oldValue = 0;
566 if (m_operator == OpPlusPlus)
567 generator.emitPreInc(srcDst: value.get());
568 else
569 generator.emitPreDec(srcDst: value.get());
570 } else {
571 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(dst: generator.finalDestination(originalDst: dst), srcDst: value.get()) : generator.emitPostDec(dst: generator.finalDestination(originalDst: dst), srcDst: value.get());
572 }
573 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
574 generator.emitPutByVal(base: base.get(), property: property.get(), value: value.get());
575 return oldValue;
576}
577
578// ------------------------------ PostfixDotNode ----------------------------------
579
580RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
581{
582 RefPtr<RegisterID> base = generator.emitNode(n: m_base);
583
584 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
585 RefPtr<RegisterID> value = generator.emitGetById(dst: generator.newTemporary(), base: base.get(), property: m_ident);
586 RegisterID* oldValue;
587 if (dst == generator.ignoredResult()) {
588 oldValue = 0;
589 if (m_operator == OpPlusPlus)
590 generator.emitPreInc(srcDst: value.get());
591 else
592 generator.emitPreDec(srcDst: value.get());
593 } else {
594 oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(dst: generator.finalDestination(originalDst: dst), srcDst: value.get()) : generator.emitPostDec(dst: generator.finalDestination(originalDst: dst), srcDst: value.get());
595 }
596 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
597 generator.emitPutById(base: base.get(), property: m_ident, value: value.get());
598 return oldValue;
599}
600
601// ------------------------------ PostfixErrorNode -----------------------------------
602
603RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
604{
605 return emitThrowError(generator, type: ReferenceError, message: 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
612RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
613{
614 if (generator.registerFor(m_ident))
615 return generator.emitLoad(dst: generator.finalDestination(originalDst: dst), false);
616
617 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
618 RegisterID* base = generator.emitResolveBase(dst: generator.tempDestination(dst), property: m_ident);
619 return generator.emitDeleteById(dst: generator.finalDestination(originalDst: dst, tempDst: base), base, m_ident);
620}
621
622// ------------------------------ DeleteBracketNode -----------------------------------
623
624RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
625{
626 RefPtr<RegisterID> r0 = generator.emitNode(n: m_base);
627 RegisterID* r1 = generator.emitNode(n: m_subscript);
628
629 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
630 return generator.emitDeleteByVal(dst: generator.finalDestination(originalDst: dst), base: r0.get(), property: r1);
631}
632
633// ------------------------------ DeleteDotNode -----------------------------------
634
635RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
636{
637 RegisterID* r0 = generator.emitNode(n: m_base);
638
639 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
640 return generator.emitDeleteById(dst: generator.finalDestination(originalDst: dst), base: r0, m_ident);
641}
642
643// ------------------------------ DeleteValueNode -----------------------------------
644
645RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
646{
647 generator.emitNode(dst: generator.ignoredResult(), n: m_expr);
648
649 // delete on a non-location expression ignores the value and returns true
650 return generator.emitLoad(dst: generator.finalDestination(originalDst: dst), true);
651}
652
653// ------------------------------ VoidNode -------------------------------------
654
655RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
656{
657 if (dst == generator.ignoredResult()) {
658 generator.emitNode(dst: generator.ignoredResult(), n: m_expr);
659 return 0;
660 }
661 RefPtr<RegisterID> r0 = generator.emitNode(n: m_expr);
662 return generator.emitLoad(dst, jsUndefined());
663}
664
665// ------------------------------ TypeOfValueNode -----------------------------------
666
667RegisterID* 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(dst: generator.finalDestination(originalDst: dst), src: local);
673 }
674
675 RefPtr<RegisterID> scratch = generator.emitResolveBase(dst: generator.tempDestination(dst), property: m_ident);
676 generator.emitGetById(dst: scratch.get(), base: scratch.get(), property: m_ident);
677 if (dst == generator.ignoredResult())
678 return 0;
679 return generator.emitTypeOf(dst: generator.finalDestination(originalDst: dst, tempDst: scratch.get()), src: scratch.get());
680}
681
682// ------------------------------ TypeOfValueNode -----------------------------------
683
684RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
685{
686 if (dst == generator.ignoredResult()) {
687 generator.emitNode(dst: generator.ignoredResult(), n: m_expr);
688 return 0;
689 }
690 RefPtr<RegisterID> src = generator.emitNode(n: m_expr);
691 return generator.emitTypeOf(dst: generator.finalDestination(originalDst: dst), src: src.get());
692}
693
694// ------------------------------ PrefixResolveNode ----------------------------------
695
696RegisterID* 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(dst: generator.finalDestination(originalDst: dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0);
703 return generator.emitBinaryOp(op_add, dst: r0.get(), src1: local, src2: r0.get(), OperandTypes());
704 }
705
706 emitPreIncOrDec(generator, srcDst: local, oper: m_operator);
707 return generator.moveToDestinationIfNeeded(dst, src: local);
708 }
709
710 int index = 0;
711 size_t depth = 0;
712 JSObject* globalObject = 0;
713 if (generator.findScopedProperty(m_ident, index, depth, forWriting: false, globalObject) && index != missingSymbolMarker()) {
714 RefPtr<RegisterID> propDst = generator.emitGetScopedVar(dst: generator.tempDestination(dst), skip: depth, index, globalObject);
715 emitPreIncOrDec(generator, srcDst: propDst.get(), oper: m_operator);
716 generator.emitPutScopedVar(skip: depth, index, value: propDst.get(), globalObject);
717 return generator.moveToDestinationIfNeeded(dst, src: propDst.get());
718 }
719
720 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
721 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
722 RefPtr<RegisterID> base = generator.emitResolveWithBase(baseDst: generator.newTemporary(), propDst: propDst.get(), property: m_ident);
723 emitPreIncOrDec(generator, srcDst: propDst.get(), oper: m_operator);
724 generator.emitPutById(base: base.get(), property: m_ident, value: propDst.get());
725 return generator.moveToDestinationIfNeeded(dst, src: propDst.get());
726}
727
728// ------------------------------ PrefixBracketNode ----------------------------------
729
730RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
731{
732 RefPtr<RegisterID> base = generator.emitNode(n: m_base);
733 RefPtr<RegisterID> property = generator.emitNode(n: m_subscript);
734 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
735
736 generator.emitExpressionInfo(divot: divot() + m_subexpressionDivotOffset, startOffset: m_subexpressionStartOffset, endOffset: endOffset() - m_subexpressionDivotOffset);
737 RegisterID* value = generator.emitGetByVal(dst: propDst.get(), base: base.get(), property: property.get());
738 if (m_operator == OpPlusPlus)
739 generator.emitPreInc(srcDst: value);
740 else
741 generator.emitPreDec(srcDst: value);
742 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
743 generator.emitPutByVal(base: base.get(), property: property.get(), value);
744 return generator.moveToDestinationIfNeeded(dst, src: propDst.get());
745}
746
747// ------------------------------ PrefixDotNode ----------------------------------
748
749RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
750{
751 RefPtr<RegisterID> base = generator.emitNode(n: m_base);
752 RefPtr<RegisterID> propDst = generator.tempDestination(dst);
753
754 generator.emitExpressionInfo(divot: divot() + m_subexpressionDivotOffset, startOffset: m_subexpressionStartOffset, endOffset: endOffset() - m_subexpressionDivotOffset);
755 RegisterID* value = generator.emitGetById(dst: propDst.get(), base: base.get(), property: m_ident);
756 if (m_operator == OpPlusPlus)
757 generator.emitPreInc(srcDst: value);
758 else
759 generator.emitPreDec(srcDst: value);
760 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
761 generator.emitPutById(base: base.get(), property: m_ident, value);
762 return generator.moveToDestinationIfNeeded(dst, src: propDst.get());
763}
764
765// ------------------------------ PrefixErrorNode -----------------------------------
766
767RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
768{
769 return emitThrowError(generator, type: ReferenceError, message: 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
776RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
777{
778 RegisterID* src = generator.emitNode(n: m_expr);
779 return generator.emitUnaryOp(opcodeID(), dst: generator.finalDestination(originalDst: dst), src);
780}
781
782
783// ------------------------------ LogicalNotNode -----------------------------------
784
785void 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(n: expr(), trueTarget: falseTarget, falseTarget: trueTarget, fallThroughMeansTrue: !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//
824RegisterID* 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(val: 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(val: 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(val: generator.newTemporary());
851
852 // Emit code for the leftmost node ((a) in the example).
853 temporaryRegisters.append(val: generator.newTemporary());
854 RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get();
855 generator.emitNode(dst: leftMostAddChildTempRegister, n: 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(val: generator.newTemporary());
887 generator.emitNode(dst: temporaryRegisters.last().get(), n: 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(dst: leftMostAddChildTempRegister, src: 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(dst: temporaryRegisters.last().get(), src: 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(divot: emitExpressionInfoForMe->divot(), startOffset: emitExpressionInfoForMe->startOffset(), endOffset: 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(dst: temporaryRegisters[0].get(), src: lhs);
910
911 return generator.emitStrcat(dst: generator.finalDestination(originalDst: dst, tempDst: temporaryRegisters[0].get()), src: temporaryRegisters[0].get(), count: temporaryRegisters.size());
912}
913
914RegisterID* 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(dst: src.get(), n: m_expr1->isNull() ? m_expr2 : m_expr1);
925 return generator.emitUnaryOp(op_neq_null, dst: generator.finalDestination(originalDst: dst, tempDst: src.get()), src: src.get());
926 }
927 }
928
929 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(n: m_expr1, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_expr2->isPure(generator));
930 RegisterID* src2 = generator.emitNode(n: m_expr2);
931 return generator.emitBinaryOp(opcodeID, dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), src1: src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
932}
933
934RegisterID* 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(dst: src.get(), n: m_expr1->isNull() ? m_expr2 : m_expr1);
939 return generator.emitUnaryOp(op_eq_null, dst: generator.finalDestination(originalDst: dst, tempDst: src.get()), src: src.get());
940 }
941
942 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(n: m_expr1, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_expr2->isPure(generator));
943 RegisterID* src2 = generator.emitNode(n: m_expr2);
944 return generator.emitEqualityOp(op_eq, dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), src1: src1.get(), src2);
945}
946
947RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
948{
949 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(n: m_expr1, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_expr2->isPure(generator));
950 RegisterID* src2 = generator.emitNode(n: m_expr2);
951 return generator.emitEqualityOp(op_stricteq, dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), src1: src1.get(), src2);
952}
953
954RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
955{
956 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(n: m_expr1, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_expr2->isPure(generator));
957 RegisterID* src2 = generator.emitNode(n: m_expr2);
958 return generator.emitBinaryOp(opcodeID(), dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), src1: src2, src2: src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor()));
959}
960
961RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
962{
963 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(n: m_expr1, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_expr2->isPure(generator));
964 RegisterID* src2 = generator.emitNode(n: m_expr2);
965 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
966 return generator.emitBinaryOp(opcodeID(), dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), src1: src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor()));
967}
968
969RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
970{
971 RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(n: m_expr1, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_expr2->isPure(generator));
972 RefPtr<RegisterID> src2 = generator.emitNode(n: m_expr2);
973
974 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
975 generator.emitGetByIdExceptionInfo(opcodeID: op_instanceof);
976 RegisterID* src2Prototype = generator.emitGetById(dst: generator.newTemporary(), base: src2.get(), property: generator.globalData()->propertyNames->prototype);
977
978 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
979 return generator.emitInstanceOf(dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), value: src1.get(), base: src2.get(), basePrototype: src2Prototype);
980}
981
982// ------------------------------ LogicalOpNode ----------------------------
983
984RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
985{
986 RefPtr<RegisterID> temp = generator.tempDestination(dst);
987 RefPtr<Label> target = generator.newLabel();
988
989 generator.emitNode(dst: temp.get(), n: m_expr1);
990 if (m_operator == OpLogicalAnd)
991 generator.emitJumpIfFalse(cond: temp.get(), target: target.get());
992 else
993 generator.emitJumpIfTrue(cond: temp.get(), target: target.get());
994 generator.emitNode(dst: temp.get(), n: m_expr2);
995 generator.emitLabel(target.get());
996
997 return generator.moveToDestinationIfNeeded(dst, src: temp.get());
998}
999
1000void 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(n: m_expr1, trueTarget: afterExpr1.get(), falseTarget, fallThroughMeansTrue: true);
1006 else
1007 generator.emitNodeInConditionContext(n: m_expr1, trueTarget, falseTarget: afterExpr1.get(), fallThroughMeansTrue: false);
1008 generator.emitLabel(afterExpr1.get());
1009 } else {
1010 RegisterID* temp = generator.emitNode(n: m_expr1);
1011 if (m_operator == OpLogicalAnd)
1012 generator.emitJumpIfFalse(cond: temp, target: falseTarget);
1013 else
1014 generator.emitJumpIfTrue(cond: temp, target: trueTarget);
1015 }
1016
1017 if (m_expr2->hasConditionContextCodegen())
1018 generator.emitNodeInConditionContext(n: m_expr2, trueTarget, falseTarget, fallThroughMeansTrue);
1019 else {
1020 RegisterID* temp = generator.emitNode(n: m_expr2);
1021 if (fallThroughMeansTrue)
1022 generator.emitJumpIfFalse(cond: temp, target: falseTarget);
1023 else
1024 generator.emitJumpIfTrue(cond: temp, target: trueTarget);
1025 }
1026}
1027
1028// ------------------------------ ConditionalNode ------------------------------
1029
1030RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1031{
1032 RefPtr<RegisterID> newDst = generator.finalDestination(originalDst: 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(n: m_logical, trueTarget: beforeThen.get(), falseTarget: beforeElse.get(), fallThroughMeansTrue: true);
1039 generator.emitLabel(beforeThen.get());
1040 } else {
1041 RegisterID* cond = generator.emitNode(n: m_logical);
1042 generator.emitJumpIfFalse(cond, target: beforeElse.get());
1043 }
1044
1045 generator.emitNode(dst: newDst.get(), n: m_expr1);
1046 generator.emitJump(target: afterElse.get());
1047
1048 generator.emitLabel(beforeElse.get());
1049 generator.emitNode(dst: newDst.get(), n: 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?
1059static 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, lhs: 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(n: 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(divot: emitExpressionInfoForMe->divot(), startOffset: emitExpressionInfoForMe->startOffset(), endOffset: emitExpressionInfoForMe->endOffset());
1109
1110 return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
1111}
1112
1113RegisterID* 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, dst: generator.finalDestination(originalDst: dst), src1: local, m_right, oper: m_operator, types: OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1118 }
1119
1120 if (generator.leftHandSideNeedsCopy(rightHasAssignments: m_rightHasAssignments, rightIsPure: m_right->isPure(generator))) {
1121 RefPtr<RegisterID> result = generator.newTemporary();
1122 generator.emitMove(dst: result.get(), src: local);
1123 emitReadModifyAssignment(generator, dst: result.get(), src1: result.get(), m_right, oper: m_operator, types: OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1124 generator.emitMove(dst: local, src: result.get());
1125 return generator.moveToDestinationIfNeeded(dst, src: result.get());
1126 }
1127
1128 RegisterID* result = emitReadModifyAssignment(generator, dst: local, src1: local, m_right, oper: m_operator, types: OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1129 return generator.moveToDestinationIfNeeded(dst, src: result);
1130 }
1131
1132 int index = 0;
1133 size_t depth = 0;
1134 JSObject* globalObject = 0;
1135 if (generator.findScopedProperty(m_ident, index, depth, forWriting: true, globalObject) && index != missingSymbolMarker()) {
1136 RefPtr<RegisterID> src1 = generator.emitGetScopedVar(dst: generator.tempDestination(dst), skip: depth, index, globalObject);
1137 RegisterID* result = emitReadModifyAssignment(generator, dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), src1: src1.get(), m_right, oper: m_operator, types: OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1138 generator.emitPutScopedVar(skip: depth, index, value: result, globalObject);
1139 return result;
1140 }
1141
1142 RefPtr<RegisterID> src1 = generator.tempDestination(dst);
1143 generator.emitExpressionInfo(divot: divot() - startOffset() + m_ident.size(), startOffset: m_ident.size(), endOffset: 0);
1144 RefPtr<RegisterID> base = generator.emitResolveWithBase(baseDst: generator.newTemporary(), propDst: src1.get(), property: m_ident);
1145 RegisterID* result = emitReadModifyAssignment(generator, dst: generator.finalDestination(originalDst: dst, tempDst: src1.get()), src1: src1.get(), m_right, oper: m_operator, types: OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), emitExpressionInfoForMe: this);
1146 return generator.emitPutById(base: base.get(), property: m_ident, value: result);
1147}
1148
1149// ------------------------------ AssignResolveNode -----------------------------------
1150
1151RegisterID* 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, n: m_right);
1156
1157 RegisterID* result = generator.emitNode(dst: local, n: m_right);
1158 return generator.moveToDestinationIfNeeded(dst, src: result);
1159 }
1160
1161 int index = 0;
1162 size_t depth = 0;
1163 JSObject* globalObject = 0;
1164 if (generator.findScopedProperty(m_ident, index, depth, forWriting: true, globalObject) && index != missingSymbolMarker()) {
1165 if (dst == generator.ignoredResult())
1166 dst = 0;
1167 RegisterID* value = generator.emitNode(dst, n: m_right);
1168 generator.emitPutScopedVar(skip: depth, index, value, globalObject);
1169 return value;
1170 }
1171
1172 RefPtr<RegisterID> base = generator.emitResolveBase(dst: generator.newTemporary(), property: m_ident);
1173 if (dst == generator.ignoredResult())
1174 dst = 0;
1175 RegisterID* value = generator.emitNode(dst, n: m_right);
1176 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
1177 return generator.emitPutById(base: base.get(), property: m_ident, value);
1178}
1179
1180// ------------------------------ AssignDotNode -----------------------------------
1181
1182RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1183{
1184 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(n: m_base, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_right->isPure(generator));
1185 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1186 RegisterID* result = generator.emitNode(dst: value.get(), n: m_right);
1187 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
1188 generator.emitPutById(base: base.get(), property: m_ident, value: result);
1189 return generator.moveToDestinationIfNeeded(dst, src: result);
1190}
1191
1192// ------------------------------ ReadModifyDotNode -----------------------------------
1193
1194RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1195{
1196 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(n: m_base, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_right->isPure(generator));
1197
1198 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
1199 RefPtr<RegisterID> value = generator.emitGetById(dst: generator.tempDestination(dst), base: base.get(), property: m_ident);
1200 RegisterID* updatedValue = emitReadModifyAssignment(generator, dst: generator.finalDestination(originalDst: dst, tempDst: value.get()), src1: value.get(), m_right, oper: m_operator, types: OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1201
1202 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
1203 return generator.emitPutById(base: base.get(), property: m_ident, value: updatedValue);
1204}
1205
1206// ------------------------------ AssignErrorNode -----------------------------------
1207
1208RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1209{
1210 return emitThrowError(generator, type: ReferenceError, message: "Left side of assignment is not a reference.");
1211}
1212
1213// ------------------------------ AssignBracketNode -----------------------------------
1214
1215RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1216{
1217 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(n: m_base, rightHasAssignments: m_subscriptHasAssignments || m_rightHasAssignments, rightIsPure: m_subscript->isPure(generator) && m_right->isPure(generator));
1218 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(n: m_subscript, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_right->isPure(generator));
1219 RefPtr<RegisterID> value = generator.destinationForAssignResult(dst);
1220 RegisterID* result = generator.emitNode(dst: value.get(), n: m_right);
1221
1222 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
1223 generator.emitPutByVal(base: base.get(), property: property.get(), value: result);
1224 return generator.moveToDestinationIfNeeded(dst, src: result);
1225}
1226
1227// ------------------------------ ReadModifyBracketNode -----------------------------------
1228
1229RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1230{
1231 RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(n: m_base, rightHasAssignments: m_subscriptHasAssignments || m_rightHasAssignments, rightIsPure: m_subscript->isPure(generator) && m_right->isPure(generator));
1232 RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(n: m_subscript, rightHasAssignments: m_rightHasAssignments, rightIsPure: m_right->isPure(generator));
1233
1234 generator.emitExpressionInfo(divot: divot() - m_subexpressionDivotOffset, startOffset: startOffset() - m_subexpressionDivotOffset, endOffset: m_subexpressionEndOffset);
1235 RefPtr<RegisterID> value = generator.emitGetByVal(dst: generator.tempDestination(dst), base: base.get(), property: property.get());
1236 RegisterID* updatedValue = emitReadModifyAssignment(generator, dst: generator.finalDestination(originalDst: dst, tempDst: value.get()), src1: value.get(), m_right, oper: m_operator, types: OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
1237
1238 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
1239 generator.emitPutByVal(base: base.get(), property: property.get(), value: updatedValue);
1240
1241 return updatedValue;
1242}
1243
1244// ------------------------------ CommaNode ------------------------------------
1245
1246RegisterID* 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(dst: generator.ignoredResult(), n: m_expressions[i]);
1251 return generator.emitNode(dst, n: m_expressions.last());
1252}
1253
1254// ------------------------------ ConstDeclNode ------------------------------------
1255
1256RegisterID* 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(dst: local, n: m_init);
1263 }
1264
1265 if (generator.codeType() != EvalCode) {
1266 if (m_init)
1267 return generator.emitNode(n: m_init);
1268 else
1269 return generator.emitResolve(dst: generator.newTemporary(), property: 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(dst: generator.newTemporary(), property: m_ident);
1274 RegisterID* value = m_init ? generator.emitNode(n: m_init) : generator.emitLoad(dst: 0, jsUndefined());
1275 return generator.emitPutById(base: base.get(), property: m_ident, value);
1276}
1277
1278RegisterID* 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
1289RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1290{
1291 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1292 return generator.emitNode(n: m_next);
1293}
1294
1295// ------------------------------ SourceElements -------------------------------
1296
1297
1298inline StatementNode* SourceElements::lastStatement() const
1299{
1300 size_t size = m_statements.size();
1301 return size ? m_statements[size - 1] : 0;
1302}
1303
1304inline 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, n: m_statements[i]);
1309}
1310
1311// ------------------------------ BlockNode ------------------------------------
1312
1313inline StatementNode* BlockNode::lastStatement() const
1314{
1315 return m_statements ? m_statements->lastStatement() : 0;
1316}
1317
1318RegisterID* 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
1327RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1328{
1329 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1330 return dst;
1331}
1332
1333// ------------------------------ DebuggerStatementNode ---------------------------
1334
1335RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1336{
1337 generator.emitDebugHook(DidReachBreakpoint, firstLine: firstLine(), lastLine: lastLine());
1338 return dst;
1339}
1340
1341// ------------------------------ ExprStatementNode ----------------------------
1342
1343RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1344{
1345 ASSERT(m_expr);
1346 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1347 return generator.emitNode(dst, n: m_expr);
1348}
1349
1350// ------------------------------ VarStatementNode ----------------------------
1351
1352RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1353{
1354 ASSERT(m_expr);
1355 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1356 return generator.emitNode(n: m_expr);
1357}
1358
1359// ------------------------------ IfNode ---------------------------------------
1360
1361RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1362{
1363 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1364
1365 RefPtr<Label> afterThen = generator.newLabel();
1366
1367 if (m_condition->hasConditionContextCodegen()) {
1368 RefPtr<Label> beforeThen = generator.newLabel();
1369 generator.emitNodeInConditionContext(n: m_condition, trueTarget: beforeThen.get(), falseTarget: afterThen.get(), fallThroughMeansTrue: true);
1370 generator.emitLabel(beforeThen.get());
1371 } else {
1372 RegisterID* cond = generator.emitNode(n: m_condition);
1373 generator.emitJumpIfFalse(cond, target: afterThen.get());
1374 }
1375
1376 generator.emitNode(dst, n: 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
1385RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1386{
1387 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: 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(n: m_condition, trueTarget: beforeThen.get(), falseTarget: beforeElse.get(), fallThroughMeansTrue: true);
1395 generator.emitLabel(beforeThen.get());
1396 } else {
1397 RegisterID* cond = generator.emitNode(n: m_condition);
1398 generator.emitJumpIfFalse(cond, target: beforeElse.get());
1399 }
1400
1401 generator.emitNode(dst, n: m_ifBlock);
1402 generator.emitJump(target: afterElse.get());
1403
1404 generator.emitLabel(beforeElse.get());
1405
1406 generator.emitNode(dst, n: 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
1416RegisterID* 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: firstLine(), lastLine: lastLine());
1424
1425 RefPtr<RegisterID> result = generator.emitNode(dst, n: m_statement);
1426
1427 generator.emitLabel(scope->continueTarget());
1428#ifndef QT_BUILD_SCRIPT_LIB
1429 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1430#endif
1431 if (m_expr->hasConditionContextCodegen())
1432 generator.emitNodeInConditionContext(n: m_expr, trueTarget: topOfLoop.get(), falseTarget: scope->breakTarget(), fallThroughMeansTrue: false);
1433 else {
1434 RegisterID* cond = generator.emitNode(n: m_expr);
1435 generator.emitJumpIfTrue(cond, target: topOfLoop.get());
1436 }
1437
1438 generator.emitLabel(scope->breakTarget());
1439 return result.get();
1440}
1441
1442// ------------------------------ WhileNode ------------------------------------
1443
1444RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1445{
1446 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1447
1448#ifdef QT_BUILD_SCRIPT_LIB
1449 generator.emitDebugHook(WillExecuteStatement, firstLine: m_expr->lineNo(), lastLine: m_expr->lineNo());
1450#endif
1451 generator.emitJump(target: scope->continueTarget());
1452
1453 RefPtr<Label> topOfLoop = generator.newLabel();
1454 generator.emitLabel(topOfLoop.get());
1455
1456 generator.emitNode(dst, n: m_statement);
1457
1458 generator.emitLabel(scope->continueTarget());
1459#ifndef QT_BUILD_SCRIPT_LIB
1460 generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo());
1461#endif
1462
1463 if (m_expr->hasConditionContextCodegen())
1464 generator.emitNodeInConditionContext(n: m_expr, trueTarget: topOfLoop.get(), falseTarget: scope->breakTarget(), fallThroughMeansTrue: false);
1465 else {
1466 RegisterID* cond = generator.emitNode(n: m_expr);
1467 generator.emitJumpIfTrue(cond, target: topOfLoop.get());
1468 }
1469
1470 generator.emitLabel(scope->breakTarget());
1471
1472 // FIXME: This should return the last statement executed so that it can be returned as a Completion
1473 return 0;
1474}
1475
1476// ------------------------------ ForNode --------------------------------------
1477
1478RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1479{
1480 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1481
1482 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1483
1484 if (m_expr1)
1485 generator.emitNode(dst: generator.ignoredResult(), n: m_expr1);
1486
1487 RefPtr<Label> condition = generator.newLabel();
1488 generator.emitJump(target: condition.get());
1489
1490 RefPtr<Label> topOfLoop = generator.newLabel();
1491 generator.emitLabel(topOfLoop.get());
1492
1493 RefPtr<RegisterID> result = generator.emitNode(dst, n: m_statement);
1494
1495 generator.emitLabel(scope->continueTarget());
1496#ifndef QT_BUILD_SCRIPT_LIB
1497 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1498#endif
1499 if (m_expr3)
1500 generator.emitNode(dst: generator.ignoredResult(), n: m_expr3);
1501
1502 generator.emitLabel(condition.get());
1503 if (m_expr2) {
1504 if (m_expr2->hasConditionContextCodegen())
1505 generator.emitNodeInConditionContext(n: m_expr2, trueTarget: topOfLoop.get(), falseTarget: scope->breakTarget(), fallThroughMeansTrue: false);
1506 else {
1507 RegisterID* cond = generator.emitNode(n: m_expr2);
1508 generator.emitJumpIfTrue(cond, target: topOfLoop.get());
1509 }
1510 } else
1511 generator.emitJump(target: topOfLoop.get());
1512
1513 generator.emitLabel(scope->breakTarget());
1514 return result.get();
1515}
1516
1517// ------------------------------ ForInNode ------------------------------------
1518
1519RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1520{
1521 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
1522
1523 if (!m_lexpr->isLocation())
1524 return emitThrowError(generator, type: ReferenceError, message: "Left side of for-in statement is not a reference.");
1525
1526 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1527
1528 if (m_init)
1529 generator.emitNode(dst: generator.ignoredResult(), n: m_init);
1530
1531 RefPtr<RegisterID> base = generator.newTemporary();
1532 generator.emitNode(dst: base.get(), n: m_expr);
1533 RefPtr<RegisterID> i = generator.newTemporary();
1534 RefPtr<RegisterID> size = generator.newTemporary();
1535 RefPtr<RegisterID> expectedSubscript;
1536 RefPtr<RegisterID> iter = generator.emitGetPropertyNames(dst: generator.newTemporary(), base: base.get(), i: i.get(), size: size.get(), breakTarget: scope->breakTarget());
1537 generator.emitJump(target: scope->continueTarget());
1538
1539 RefPtr<Label> loopStart = generator.newLabel();
1540 generator.emitLabel(loopStart.get());
1541
1542 RegisterID* propertyName;
1543 bool optimizedForinAccess = false;
1544 if (m_lexpr->isResolveNode()) {
1545 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
1546 propertyName = generator.registerFor(ident);
1547 if (!propertyName) {
1548 propertyName = generator.newTemporary();
1549 RefPtr<RegisterID> protect = propertyName;
1550 RegisterID* base = generator.emitResolveBase(dst: generator.newTemporary(), property: ident);
1551
1552 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
1553 generator.emitPutById(base, property: ident, value: propertyName);
1554 } else {
1555 expectedSubscript = generator.emitMove(dst: generator.newTemporary(), src: propertyName);
1556 generator.pushOptimisedForIn(expectedBase: expectedSubscript.get(), iter: iter.get(), index: i.get(), propertyRegister: propertyName);
1557 optimizedForinAccess = true;
1558 }
1559 } else if (m_lexpr->isDotAccessorNode()) {
1560 DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
1561 const Identifier& ident = assignNode->identifier();
1562 propertyName = generator.newTemporary();
1563 RefPtr<RegisterID> protect = propertyName;
1564 RegisterID* base = generator.emitNode(n: assignNode->base());
1565
1566 generator.emitExpressionInfo(divot: assignNode->divot(), startOffset: assignNode->startOffset(), endOffset: assignNode->endOffset());
1567 generator.emitPutById(base, property: ident, value: propertyName);
1568 } else {
1569 ASSERT(m_lexpr->isBracketAccessorNode());
1570 BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
1571 propertyName = generator.newTemporary();
1572 RefPtr<RegisterID> protect = propertyName;
1573 RefPtr<RegisterID> base = generator.emitNode(n: assignNode->base());
1574 RegisterID* subscript = generator.emitNode(n: assignNode->subscript());
1575
1576 generator.emitExpressionInfo(divot: assignNode->divot(), startOffset: assignNode->startOffset(), endOffset: assignNode->endOffset());
1577 generator.emitPutByVal(base: base.get(), property: subscript, value: propertyName);
1578 }
1579
1580 generator.emitNode(dst, n: m_statement);
1581
1582 if (optimizedForinAccess)
1583 generator.popOptimisedForIn();
1584
1585 generator.emitLabel(scope->continueTarget());
1586 generator.emitNextPropertyName(dst: propertyName, base: base.get(), i: i.get(), size: size.get(), iter: iter.get(), target: loopStart.get());
1587#ifndef QT_BUILD_SCRIPT_LIB
1588 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1589#endif
1590 generator.emitLabel(scope->breakTarget());
1591 return dst;
1592}
1593
1594// ------------------------------ ContinueNode ---------------------------------
1595
1596// ECMA 12.7
1597RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1598{
1599 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1600
1601 LabelScope* scope = generator.continueTarget(m_ident);
1602
1603 if (!scope)
1604 return m_ident.isEmpty()
1605 ? emitThrowError(generator, type: SyntaxError, message: "Invalid continue statement.")
1606 : emitThrowError(generator, type: SyntaxError, messageTemplate: "Undefined label: '%s'.", label: m_ident);
1607
1608 generator.emitJumpScopes(target: scope->continueTarget(), targetScopeDepth: scope->scopeDepth());
1609 return dst;
1610}
1611
1612// ------------------------------ BreakNode ------------------------------------
1613
1614// ECMA 12.8
1615RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1616{
1617 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1618
1619 LabelScope* scope = generator.breakTarget(m_ident);
1620
1621 if (!scope)
1622 return m_ident.isEmpty()
1623 ? emitThrowError(generator, type: SyntaxError, message: "Invalid break statement.")
1624 : emitThrowError(generator, type: SyntaxError, messageTemplate: "Undefined label: '%s'.", label: m_ident);
1625
1626 generator.emitJumpScopes(target: scope->breakTarget(), targetScopeDepth: scope->scopeDepth());
1627 return dst;
1628}
1629
1630// ------------------------------ ReturnNode -----------------------------------
1631
1632RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1633{
1634 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1635 if (generator.codeType() != FunctionCode)
1636 return emitThrowError(generator, type: SyntaxError, message: "Invalid return statement.");
1637
1638 if (dst == generator.ignoredResult())
1639 dst = 0;
1640 RegisterID* r0 = m_value ? generator.emitNode(dst, n: m_value) : generator.emitLoad(dst, jsUndefined());
1641 RefPtr<RegisterID> returnRegister;
1642 if (generator.scopeDepth()) {
1643 RefPtr<Label> l0 = generator.newLabel();
1644 if (generator.hasFinaliser() && !r0->isTemporary()) {
1645 returnRegister = generator.emitMove(dst: generator.newTemporary(), src: r0);
1646 r0 = returnRegister.get();
1647 }
1648 generator.emitJumpScopes(target: l0.get(), targetScopeDepth: 0);
1649 generator.emitLabel(l0.get());
1650 }
1651 generator.emitDebugHook(WillLeaveCallFrame, firstLine: firstLine(), lastLine: lastLine());
1652 return generator.emitReturn(src: r0);
1653}
1654
1655// ------------------------------ WithNode -------------------------------------
1656
1657RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1658{
1659 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1660
1661 RefPtr<RegisterID> scope = generator.newTemporary();
1662 generator.emitNode(dst: scope.get(), n: m_expr); // scope must be protected until popped
1663 generator.emitExpressionInfo(divot: m_divot, startOffset: m_expressionLength, endOffset: 0);
1664 generator.emitPushScope(scope: scope.get());
1665 RegisterID* result = generator.emitNode(dst, n: m_statement);
1666 generator.emitPopScope();
1667 return result;
1668}
1669
1670// ------------------------------ CaseClauseNode --------------------------------
1671
1672inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1673{
1674 if (m_statements)
1675 m_statements->emitBytecode(generator, dst);
1676}
1677
1678// ------------------------------ CaseBlockNode --------------------------------
1679
1680enum SwitchKind {
1681 SwitchUnset = 0,
1682 SwitchNumber = 1,
1683 SwitchString = 2,
1684 SwitchNeither = 3
1685};
1686
1687static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num)
1688{
1689 for (; list; list = list->getNext()) {
1690 ExpressionNode* clauseExpression = list->getClause()->expr();
1691 literalVector.append(val: clauseExpression);
1692 if (clauseExpression->isNumber()) {
1693 double value = static_cast<NumberNode*>(clauseExpression)->value();
1694 int32_t intVal = static_cast<int32_t>(value);
1695 if ((typeForTable & ~SwitchNumber) || (intVal != value)) {
1696 typeForTable = SwitchNeither;
1697 break;
1698 }
1699 if (intVal < min_num)
1700 min_num = intVal;
1701 if (intVal > max_num)
1702 max_num = intVal;
1703 typeForTable = SwitchNumber;
1704 continue;
1705 }
1706 if (clauseExpression->isString()) {
1707 if (typeForTable & ~SwitchString) {
1708 typeForTable = SwitchNeither;
1709 break;
1710 }
1711 const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
1712 if (singleCharacterSwitch &= value.size() == 1) {
1713 int32_t intVal = value.rep()->data()[0];
1714 if (intVal < min_num)
1715 min_num = intVal;
1716 if (intVal > max_num)
1717 max_num = intVal;
1718 }
1719 typeForTable = SwitchString;
1720 continue;
1721 }
1722 typeForTable = SwitchNeither;
1723 break;
1724 }
1725}
1726
1727SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num)
1728{
1729 SwitchKind typeForTable = SwitchUnset;
1730 bool singleCharacterSwitch = true;
1731
1732 processClauseList(list: m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1733 processClauseList(list: m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num);
1734
1735 if (typeForTable == SwitchUnset || typeForTable == SwitchNeither)
1736 return SwitchInfo::SwitchNone;
1737
1738 if (typeForTable == SwitchNumber) {
1739 int32_t range = max_num - min_num;
1740 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1741 return SwitchInfo::SwitchImmediate;
1742 return SwitchInfo::SwitchNone;
1743 }
1744
1745 ASSERT(typeForTable == SwitchString);
1746
1747 if (singleCharacterSwitch) {
1748 int32_t range = max_num - min_num;
1749 if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10)
1750 return SwitchInfo::SwitchCharacter;
1751 }
1752
1753 return SwitchInfo::SwitchString;
1754}
1755
1756RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst)
1757{
1758 RefPtr<Label> defaultLabel;
1759 Vector<RefPtr<Label>, 8> labelVector;
1760 Vector<ExpressionNode*, 8> literalVector;
1761 int32_t min_num = std::numeric_limits<int32_t>::max();
1762 int32_t max_num = std::numeric_limits<int32_t>::min();
1763 SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num);
1764
1765 if (switchType != SwitchInfo::SwitchNone) {
1766 // Prepare the various labels
1767 for (uint32_t i = 0; i < literalVector.size(); i++)
1768 labelVector.append(val: generator.newLabel());
1769 defaultLabel = generator.newLabel();
1770 generator.beginSwitch(switchExpression, switchType);
1771 } else {
1772 // Setup jumps
1773 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1774 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1775 generator.emitNode(dst: clauseVal.get(), n: list->getClause()->expr());
1776 generator.emitBinaryOp(op_stricteq, dst: clauseVal.get(), src1: clauseVal.get(), src2: switchExpression, OperandTypes());
1777 labelVector.append(val: generator.newLabel());
1778 generator.emitJumpIfTrue(cond: clauseVal.get(), target: labelVector[labelVector.size() - 1].get());
1779 }
1780
1781 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1782 RefPtr<RegisterID> clauseVal = generator.newTemporary();
1783 generator.emitNode(dst: clauseVal.get(), n: list->getClause()->expr());
1784 generator.emitBinaryOp(op_stricteq, dst: clauseVal.get(), src1: clauseVal.get(), src2: switchExpression, OperandTypes());
1785 labelVector.append(val: generator.newLabel());
1786 generator.emitJumpIfTrue(cond: clauseVal.get(), target: labelVector[labelVector.size() - 1].get());
1787 }
1788 defaultLabel = generator.newLabel();
1789 generator.emitJump(target: defaultLabel.get());
1790 }
1791
1792 RegisterID* result = 0;
1793
1794 size_t i = 0;
1795 for (ClauseListNode* list = m_list1; list; list = list->getNext()) {
1796 generator.emitLabel(labelVector[i++].get());
1797 list->getClause()->emitBytecode(generator, dst);
1798 }
1799
1800 if (m_defaultClause) {
1801 generator.emitLabel(defaultLabel.get());
1802 m_defaultClause->emitBytecode(generator, dst);
1803 }
1804
1805 for (ClauseListNode* list = m_list2; list; list = list->getNext()) {
1806 generator.emitLabel(labelVector[i++].get());
1807 list->getClause()->emitBytecode(generator, dst);
1808 }
1809 if (!m_defaultClause)
1810 generator.emitLabel(defaultLabel.get());
1811
1812 ASSERT(i == labelVector.size());
1813 if (switchType != SwitchInfo::SwitchNone) {
1814 ASSERT(labelVector.size() == literalVector.size());
1815 generator.endSwitch(clauseCount: labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel: defaultLabel.get(), min: min_num, range: max_num);
1816 }
1817 return result;
1818}
1819
1820// ------------------------------ SwitchNode -----------------------------------
1821
1822RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1823{
1824 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1825
1826 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch);
1827
1828 RefPtr<RegisterID> r0 = generator.emitNode(n: m_expr);
1829 RegisterID* r1 = m_block->emitBytecodeForBlock(generator, switchExpression: r0.get(), dst);
1830
1831 generator.emitLabel(scope->breakTarget());
1832 return r1;
1833}
1834
1835// ------------------------------ LabelNode ------------------------------------
1836
1837RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1838{
1839 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1840
1841 if (generator.breakTarget(m_name))
1842 return emitThrowError(generator, type: SyntaxError, messageTemplate: "Duplicate label: %s.", label: m_name);
1843
1844 RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
1845 RegisterID* r0 = generator.emitNode(dst, n: m_statement);
1846
1847 generator.emitLabel(scope->breakTarget());
1848 return r0;
1849}
1850
1851// ------------------------------ ThrowNode ------------------------------------
1852
1853RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1854{
1855 generator.emitDebugHook(WillExecuteStatement, firstLine: firstLine(), lastLine: lastLine());
1856
1857 if (dst == generator.ignoredResult())
1858 dst = 0;
1859 RefPtr<RegisterID> expr = generator.emitNode(n: m_expr);
1860 generator.emitExpressionInfo(divot: divot(), startOffset: startOffset(), endOffset: endOffset());
1861 generator.emitThrow(exc: expr.get());
1862 return 0;
1863}
1864
1865// ------------------------------ TryNode --------------------------------------
1866
1867RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1868{
1869 // NOTE: The catch and finally blocks must be labeled explicitly, so the
1870 // optimizer knows they may be jumped to from anywhere.
1871
1872#ifndef QT_BUILD_SCRIPT_LIB
1873 generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
1874#endif
1875
1876 RefPtr<Label> tryStartLabel = generator.newLabel();
1877 RefPtr<Label> finallyStart;
1878 RefPtr<RegisterID> finallyReturnAddr;
1879 if (m_finallyBlock) {
1880 finallyStart = generator.newLabel();
1881 finallyReturnAddr = generator.newTemporary();
1882 generator.pushFinallyContext(target: finallyStart.get(), returnAddrDst: finallyReturnAddr.get());
1883 }
1884
1885 generator.emitLabel(tryStartLabel.get());
1886 generator.emitNode(dst, n: m_tryBlock);
1887
1888 if (m_catchBlock) {
1889 RefPtr<Label> catchEndLabel = generator.newLabel();
1890
1891 // Normal path: jump over the catch block.
1892 generator.emitJump(target: catchEndLabel.get());
1893
1894 // Uncaught exception path: the catch block.
1895 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
1896 RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), start: tryStartLabel.get(), end: here.get());
1897 if (m_catchHasEval) {
1898 RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(dst: generator.newTemporary());
1899 generator.emitPutById(base: dynamicScopeObject.get(), property: m_exceptionIdent, value: exceptionRegister.get());
1900 generator.emitMove(dst: exceptionRegister.get(), src: dynamicScopeObject.get());
1901 generator.emitPushScope(scope: exceptionRegister.get());
1902 } else
1903 generator.emitPushNewScope(dst: exceptionRegister.get(), property: m_exceptionIdent, value: exceptionRegister.get());
1904 generator.emitNode(dst, n: m_catchBlock);
1905 generator.emitPopScope();
1906 generator.emitLabel(catchEndLabel.get());
1907 }
1908
1909 if (m_finallyBlock) {
1910 generator.popFinallyContext();
1911 // there may be important registers live at the time we jump
1912 // to a finally block (such as for a return or throw) so we
1913 // ref the highest register ever used as a conservative
1914 // approach to not clobbering anything important
1915 RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
1916 RefPtr<Label> finallyEndLabel = generator.newLabel();
1917
1918 // Normal path: invoke the finally block, then jump over it.
1919 generator.emitJumpSubroutine(retAddrDst: finallyReturnAddr.get(), finallyStart.get());
1920 generator.emitJump(target: finallyEndLabel.get());
1921
1922 // Uncaught exception path: invoke the finally block, then re-throw the exception.
1923 RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
1924 RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), start: tryStartLabel.get(), end: here.get());
1925 generator.emitJumpSubroutine(retAddrDst: finallyReturnAddr.get(), finallyStart.get());
1926 generator.emitThrow(exc: tempExceptionRegister.get());
1927
1928 // The finally block.
1929 generator.emitLabel(finallyStart.get());
1930 generator.emitNode(dst, n: m_finallyBlock);
1931 generator.emitSubroutineReturn(retAddrSrc: finallyReturnAddr.get());
1932
1933 generator.emitLabel(finallyEndLabel.get());
1934 }
1935
1936 return dst;
1937}
1938
1939// ------------------------------ ScopeNode -----------------------------
1940
1941inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst)
1942{
1943 if (m_data->m_statements)
1944 m_data->m_statements->emitBytecode(generator, dst);
1945}
1946
1947// ------------------------------ ProgramNode -----------------------------
1948
1949RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1950{
1951 generator.emitDebugHook(WillExecuteProgram, firstLine: firstLine(), lastLine: lastLine());
1952
1953 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1954 generator.emitLoad(dst: dstRegister.get(), jsUndefined());
1955 emitStatementsBytecode(generator, dst: dstRegister.get());
1956
1957 generator.emitDebugHook(DidExecuteProgram, firstLine: firstLine(), lastLine: lastLine());
1958 generator.emitEnd(src: dstRegister.get());
1959 return 0;
1960}
1961
1962// ------------------------------ EvalNode -----------------------------
1963
1964RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1965{
1966 generator.emitDebugHook(WillExecuteProgram, firstLine: firstLine(), lastLine: lastLine());
1967
1968 RefPtr<RegisterID> dstRegister = generator.newTemporary();
1969 generator.emitLoad(dst: dstRegister.get(), jsUndefined());
1970 emitStatementsBytecode(generator, dst: dstRegister.get());
1971
1972 generator.emitDebugHook(DidExecuteProgram, firstLine: firstLine(), lastLine: lastLine());
1973 generator.emitEnd(src: dstRegister.get());
1974 return 0;
1975}
1976
1977// ------------------------------ FunctionBodyNode -----------------------------
1978
1979RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
1980{
1981 generator.emitDebugHook(DidEnterCallFrame, firstLine: firstLine(), lastLine: lastLine());
1982 emitStatementsBytecode(generator, dst: generator.ignoredResult());
1983 StatementNode* singleStatement = this->singleStatement();
1984 if (singleStatement && singleStatement->isBlock()) {
1985 StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
1986 if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
1987 return 0;
1988 }
1989
1990 RegisterID* r0 = generator.emitLoad(dst: 0, jsUndefined());
1991 generator.emitDebugHook(WillLeaveCallFrame, firstLine: firstLine(), lastLine: lastLine());
1992 generator.emitReturn(src: r0);
1993 return 0;
1994}
1995
1996// ------------------------------ FuncDeclNode ---------------------------------
1997
1998RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
1999{
2000 if (dst == generator.ignoredResult())
2001 dst = 0;
2002 return dst;
2003}
2004
2005// ------------------------------ FuncExprNode ---------------------------------
2006
2007RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
2008{
2009 return generator.emitNewFunctionExpression(dst: generator.finalDestination(originalDst: dst), func: this);
2010}
2011
2012} // namespace JSC
2013

source code of qtscript/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/NodesCodegen.cpp