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

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

https://bugs.webkit.org/show_bug.cgi?id=32454
Refactor construction of simple strings to avoid string concatenation.

Reviewed by Oliver Hunt.

Building strings through concatenation has a memory and performance cost -
a memory cost since we must over-allocate the buffer to leave space to append
into, and performance in that the string may still require reallocation (and
thus copying during construction). Instead move the full construction to
within a single function call (makeString), so that the arguments' lengths
can be calculated and an appropriate sized buffer allocated before copying
any characters.

~No performance change (~2% progression on date tests).

  • bytecode/CodeBlock.cpp:

(JSC::escapeQuotes):
(JSC::valueToSourceString):
(JSC::constantName):
(JSC::idName):
(JSC::CodeBlock::registerName):
(JSC::regexpToSourceString):
(JSC::regexpName):

  • bytecompiler/NodesCodegen.cpp:

(JSC::substitute):

  • profiler/Profiler.cpp:

(JSC::Profiler::createCallIdentifier):

  • runtime/DateConstructor.cpp:

(JSC::callDate):

  • runtime/DateConversion.cpp:

(JSC::formatDate):
(JSC::formatDateUTCVariant):
(JSC::formatTime):
(JSC::formatTimeUTC):

  • runtime/DateConversion.h:

(JSC::):

  • runtime/DatePrototype.cpp:

(JSC::dateProtoFuncToString):
(JSC::dateProtoFuncToUTCString):
(JSC::dateProtoFuncToDateString):
(JSC::dateProtoFuncToTimeString):
(JSC::dateProtoFuncToGMTString):

  • runtime/ErrorPrototype.cpp:

(JSC::errorProtoFuncToString):

  • runtime/ExceptionHelpers.cpp:

(JSC::createUndefinedVariableError):
(JSC::createErrorMessage):
(JSC::createInvalidParamError):

  • runtime/FunctionPrototype.cpp:

(JSC::insertSemicolonIfNeeded):
(JSC::functionProtoFuncToString):

  • runtime/ObjectPrototype.cpp:

(JSC::objectProtoFuncToString):

  • runtime/RegExpConstructor.cpp:

(JSC::constructRegExp):

  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::match):

  • runtime/RegExpPrototype.cpp:

(JSC::regExpProtoFuncCompile):
(JSC::regExpProtoFuncToString):

  • runtime/StringPrototype.cpp:

(JSC::stringProtoFuncBig):
(JSC::stringProtoFuncSmall):
(JSC::stringProtoFuncBlink):
(JSC::stringProtoFuncBold):
(JSC::stringProtoFuncFixed):
(JSC::stringProtoFuncItalics):
(JSC::stringProtoFuncStrike):
(JSC::stringProtoFuncSub):
(JSC::stringProtoFuncSup):
(JSC::stringProtoFuncFontcolor):
(JSC::stringProtoFuncFontsize):
(JSC::stringProtoFuncAnchor):

  • runtime/UString.h:

(JSC::):
(JSC::makeString):

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