]>
Commit | Line | Data |
---|---|---|
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 | ||
29 | #include "BytecodeGenerator.h" | |
30 | #include "CallFrame.h" | |
31 | #include "JSGlobalObject.h" | |
32 | #include "JSStaticScopeObject.h" | |
33 | #include "LabelScope.h" | |
34 | #include "Parser.h" | |
35 | #include "PropertyNameArray.h" | |
36 | #include "RegExpObject.h" | |
37 | #include "SamplingTool.h" | |
38 | #include "Debugger.h" | |
39 | #include "Lexer.h" | |
40 | #include "Operations.h" | |
41 | #include <math.h> | |
42 | #include <wtf/Assertions.h> | |
43 | #include <wtf/HashCountedSet.h> | |
44 | #include <wtf/HashSet.h> | |
45 | #include <wtf/MathExtras.h> | |
46 | #include <wtf/RefCountedLeakCounter.h> | |
47 | #include <wtf/Threading.h> | |
48 | ||
49 | using namespace WTF; | |
50 | ||
51 | namespace JSC { | |
52 | ||
53 | static void substitute(UString& string, const UString& substring) JSC_FAST_CALL; | |
54 | ||
55 | // ------------------------------ NodeReleaser -------------------------------- | |
56 | ||
57 | class NodeReleaser : Noncopyable { | |
58 | public: | |
59 | // Call this function inside the destructor of a class derived from Node. | |
60 | // This will traverse the tree below this node, destroying all of those nodes, | |
61 | // but without relying on recursion. | |
62 | static void releaseAllNodes(ParserRefCounted* root); | |
63 | ||
64 | // Call this on each node in a the releaseNodes virtual function. | |
65 | // It gives the node to the NodeReleaser, which will then release the | |
66 | // node later at the end of the releaseAllNodes process. | |
67 | template <typename T> void release(RefPtr<T>& node) { if (node) adopt(node.release()); } | |
68 | void release(RefPtr<FunctionBodyNode>& node) { if (node) adoptFunctionBodyNode(node); } | |
69 | ||
70 | private: | |
71 | NodeReleaser() { } | |
72 | ~NodeReleaser() { } | |
73 | ||
74 | void adopt(PassRefPtr<ParserRefCounted>); | |
75 | void adoptFunctionBodyNode(RefPtr<FunctionBodyNode>&); | |
76 | ||
77 | typedef Vector<RefPtr<ParserRefCounted> > NodeReleaseVector; | |
78 | OwnPtr<NodeReleaseVector> m_vector; | |
79 | }; | |
80 | ||
81 | void NodeReleaser::releaseAllNodes(ParserRefCounted* root) | |
82 | { | |
83 | ASSERT(root); | |
84 | NodeReleaser releaser; | |
85 | root->releaseNodes(releaser); | |
86 | if (!releaser.m_vector) | |
87 | return; | |
88 | // Note: The call to release.m_vector->size() is intentionally inside | |
89 | // the loop, since calls to releaseNodes are expected to increase the size. | |
90 | for (size_t i = 0; i < releaser.m_vector->size(); ++i) { | |
91 | ParserRefCounted* node = (*releaser.m_vector)[i].get(); | |
92 | if (node->hasOneRef()) | |
93 | node->releaseNodes(releaser); | |
94 | } | |
95 | } | |
96 | ||
97 | void NodeReleaser::adopt(PassRefPtr<ParserRefCounted> node) | |
98 | { | |
99 | ASSERT(node); | |
100 | if (!node->hasOneRef()) | |
101 | return; | |
102 | if (!m_vector) | |
103 | m_vector.set(new NodeReleaseVector); | |
104 | m_vector->append(node); | |
105 | } | |
106 | ||
107 | void NodeReleaser::adoptFunctionBodyNode(RefPtr<FunctionBodyNode>& functionBodyNode) | |
108 | { | |
109 | // This sidesteps a problem where if you assign a PassRefPtr<FunctionBodyNode> | |
110 | // to a PassRefPtr<Node> we leave the two reference counts (FunctionBodyNode | |
111 | // and ParserRefCounted) unbalanced. It would be nice to fix this problem in | |
112 | // a cleaner way -- perhaps we could remove the FunctionBodyNode reference | |
113 | // count at some point. | |
114 | RefPtr<Node> node = functionBodyNode; | |
115 | functionBodyNode = 0; | |
116 | adopt(node.release()); | |
117 | } | |
118 | ||
119 | // ------------------------------ ParserRefCounted ----------------------------------------- | |
120 | ||
121 | #ifndef NDEBUG | |
122 | static RefCountedLeakCounter parserRefCountedCounter("JSC::Node"); | |
123 | #endif | |
124 | ||
125 | ParserRefCounted::ParserRefCounted(JSGlobalData* globalData) | |
126 | : m_globalData(globalData) | |
127 | { | |
128 | #ifndef NDEBUG | |
129 | parserRefCountedCounter.increment(); | |
130 | #endif | |
131 | if (!m_globalData->newParserObjects) | |
132 | m_globalData->newParserObjects = new HashSet<ParserRefCounted*>; | |
133 | m_globalData->newParserObjects->add(this); | |
134 | ASSERT(m_globalData->newParserObjects->contains(this)); | |
135 | } | |
136 | ||
137 | ParserRefCounted::~ParserRefCounted() | |
138 | { | |
139 | #ifndef NDEBUG | |
140 | parserRefCountedCounter.decrement(); | |
141 | #endif | |
142 | } | |
143 | ||
144 | void ParserRefCounted::releaseNodes(NodeReleaser&) | |
145 | { | |
146 | } | |
147 | ||
148 | void ParserRefCounted::ref() | |
149 | { | |
150 | // bumping from 0 to 1 is just removing from the new nodes set | |
151 | if (m_globalData->newParserObjects) { | |
152 | HashSet<ParserRefCounted*>::iterator it = m_globalData->newParserObjects->find(this); | |
153 | if (it != m_globalData->newParserObjects->end()) { | |
154 | m_globalData->newParserObjects->remove(it); | |
155 | ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this)); | |
156 | return; | |
157 | } | |
158 | } | |
159 | ||
160 | ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); | |
161 | ||
162 | if (!m_globalData->parserObjectExtraRefCounts) | |
163 | m_globalData->parserObjectExtraRefCounts = new HashCountedSet<ParserRefCounted*>; | |
164 | m_globalData->parserObjectExtraRefCounts->add(this); | |
165 | } | |
166 | ||
167 | void ParserRefCounted::deref() | |
168 | { | |
169 | ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); | |
170 | ||
171 | if (!m_globalData->parserObjectExtraRefCounts) { | |
172 | delete this; | |
173 | return; | |
174 | } | |
175 | ||
176 | HashCountedSet<ParserRefCounted*>::iterator it = m_globalData->parserObjectExtraRefCounts->find(this); | |
177 | if (it == m_globalData->parserObjectExtraRefCounts->end()) | |
178 | delete this; | |
179 | else | |
180 | m_globalData->parserObjectExtraRefCounts->remove(it); | |
181 | } | |
182 | ||
183 | bool ParserRefCounted::hasOneRef() | |
184 | { | |
185 | if (m_globalData->newParserObjects && m_globalData->newParserObjects->contains(this)) { | |
186 | ASSERT(!m_globalData->parserObjectExtraRefCounts || !m_globalData->parserObjectExtraRefCounts->contains(this)); | |
187 | return false; | |
188 | } | |
189 | ||
190 | ASSERT(!m_globalData->newParserObjects || !m_globalData->newParserObjects->contains(this)); | |
191 | ||
192 | if (!m_globalData->parserObjectExtraRefCounts) | |
193 | return true; | |
194 | ||
195 | return !m_globalData->parserObjectExtraRefCounts->contains(this); | |
196 | } | |
197 | ||
198 | void ParserRefCounted::deleteNewObjects(JSGlobalData* globalData) | |
199 | { | |
200 | if (!globalData->newParserObjects) | |
201 | return; | |
202 | ||
203 | #ifndef NDEBUG | |
204 | HashSet<ParserRefCounted*>::iterator end = globalData->newParserObjects->end(); | |
205 | for (HashSet<ParserRefCounted*>::iterator it = globalData->newParserObjects->begin(); it != end; ++it) | |
206 | ASSERT(!globalData->parserObjectExtraRefCounts || !globalData->parserObjectExtraRefCounts->contains(*it)); | |
207 | #endif | |
208 | deleteAllValues(*globalData->newParserObjects); | |
209 | delete globalData->newParserObjects; | |
210 | globalData->newParserObjects = 0; | |
211 | } | |
212 | ||
213 | // ------------------------------ Node -------------------------------- | |
214 | ||
215 | Node::Node(JSGlobalData* globalData) | |
216 | : ParserRefCounted(globalData) | |
217 | { | |
218 | m_line = globalData->lexer->lineNo(); | |
219 | } | |
220 | ||
221 | // ------------------------------ ThrowableExpressionData -------------------------------- | |
222 | ||
223 | static void substitute(UString& string, const UString& substring) | |
224 | { | |
225 | int position = string.find("%s"); | |
226 | ASSERT(position != -1); | |
227 | UString newString = string.substr(0, position); | |
228 | newString.append(substring); | |
229 | newString.append(string.substr(position + 2)); | |
230 | string = newString; | |
231 | } | |
232 | ||
233 | RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg) | |
234 | { | |
235 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
236 | RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), msg)); | |
237 | generator.emitThrow(exception); | |
238 | return exception; | |
239 | } | |
240 | ||
241 | RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType e, const char* msg, const Identifier& label) | |
242 | { | |
243 | UString message = msg; | |
244 | substitute(message, label.ustring()); | |
245 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
246 | RegisterID* exception = generator.emitNewError(generator.newTemporary(), e, jsString(generator.globalData(), message)); | |
247 | generator.emitThrow(exception); | |
248 | return exception; | |
249 | } | |
250 | ||
251 | // ------------------------------ StatementNode -------------------------------- | |
252 | ||
253 | StatementNode::StatementNode(JSGlobalData* globalData) | |
254 | : Node(globalData) | |
255 | , m_lastLine(-1) | |
256 | { | |
257 | } | |
258 | ||
259 | void StatementNode::setLoc(int firstLine, int lastLine) | |
260 | { | |
261 | m_line = firstLine; | |
262 | m_lastLine = lastLine; | |
263 | } | |
264 | ||
265 | // ------------------------------ SourceElements -------------------------------- | |
266 | ||
267 | void SourceElements::append(PassRefPtr<StatementNode> statement) | |
268 | { | |
269 | if (statement->isEmptyStatement()) | |
270 | return; | |
271 | ||
272 | m_statements.append(statement); | |
273 | } | |
274 | ||
275 | // ------------------------------ NullNode ------------------------------------- | |
276 | ||
277 | RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
278 | { | |
279 | if (dst == generator.ignoredResult()) | |
280 | return 0; | |
281 | return generator.emitLoad(dst, jsNull()); | |
282 | } | |
283 | ||
284 | // ------------------------------ BooleanNode ---------------------------------- | |
285 | ||
286 | RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
287 | { | |
288 | if (dst == generator.ignoredResult()) | |
289 | return 0; | |
290 | return generator.emitLoad(dst, m_value); | |
291 | } | |
292 | ||
293 | // ------------------------------ NumberNode ----------------------------------- | |
294 | ||
295 | RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
296 | { | |
297 | if (dst == generator.ignoredResult()) | |
298 | return 0; | |
299 | return generator.emitLoad(dst, m_double); | |
300 | } | |
301 | ||
302 | // ------------------------------ StringNode ----------------------------------- | |
303 | ||
304 | RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
305 | { | |
306 | if (dst == generator.ignoredResult()) | |
307 | return 0; | |
308 | return generator.emitLoad(dst, m_value); | |
309 | } | |
310 | ||
311 | // ------------------------------ RegExpNode ----------------------------------- | |
312 | ||
313 | RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
314 | { | |
315 | RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern, m_flags); | |
316 | if (!regExp->isValid()) | |
317 | return emitThrowError(generator, SyntaxError, ("Invalid regular expression: " + UString(regExp->errorMessage())).UTF8String().c_str()); | |
318 | if (dst == generator.ignoredResult()) | |
319 | return 0; | |
320 | return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); | |
321 | } | |
322 | ||
323 | // ------------------------------ ThisNode ------------------------------------- | |
324 | ||
325 | RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
326 | { | |
327 | if (dst == generator.ignoredResult()) | |
328 | return 0; | |
329 | return generator.moveToDestinationIfNeeded(dst, generator.thisRegister()); | |
330 | } | |
331 | ||
332 | // ------------------------------ ResolveNode ---------------------------------- | |
333 | ||
334 | bool ResolveNode::isPure(BytecodeGenerator& generator) const | |
335 | { | |
336 | return generator.isLocal(m_ident); | |
337 | } | |
338 | ||
339 | RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
340 | { | |
341 | if (RegisterID* local = generator.registerFor(m_ident)) { | |
342 | if (dst == generator.ignoredResult()) | |
343 | return 0; | |
344 | return generator.moveToDestinationIfNeeded(dst, local); | |
345 | } | |
346 | ||
347 | generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0); | |
348 | return generator.emitResolve(generator.finalDestination(dst), m_ident); | |
349 | } | |
350 | ||
351 | // ------------------------------ ElementNode ------------------------------------ | |
352 | ||
353 | ElementNode::~ElementNode() | |
354 | { | |
355 | NodeReleaser::releaseAllNodes(this); | |
356 | } | |
357 | ||
358 | void ElementNode::releaseNodes(NodeReleaser& releaser) | |
359 | { | |
360 | releaser.release(m_next); | |
361 | releaser.release(m_node); | |
362 | } | |
363 | ||
364 | // ------------------------------ ArrayNode ------------------------------------ | |
365 | ||
366 | ArrayNode::~ArrayNode() | |
367 | { | |
368 | NodeReleaser::releaseAllNodes(this); | |
369 | } | |
370 | ||
371 | void ArrayNode::releaseNodes(NodeReleaser& releaser) | |
372 | { | |
373 | releaser.release(m_element); | |
374 | } | |
375 | ||
376 | RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
377 | { | |
378 | // FIXME: Should we put all of this code into emitNewArray? | |
379 | ||
380 | unsigned length = 0; | |
381 | ElementNode* firstPutElement; | |
382 | for (firstPutElement = m_element.get(); firstPutElement; firstPutElement = firstPutElement->next()) { | |
383 | if (firstPutElement->elision()) | |
384 | break; | |
385 | ++length; | |
386 | } | |
387 | ||
388 | if (!firstPutElement && !m_elision) | |
389 | return generator.emitNewArray(generator.finalDestination(dst), m_element.get()); | |
390 | ||
391 | RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element.get()); | |
392 | ||
393 | for (ElementNode* n = firstPutElement; n; n = n->next()) { | |
394 | RegisterID* value = generator.emitNode(n->value()); | |
395 | length += n->elision(); | |
396 | generator.emitPutByIndex(array.get(), length++, value); | |
397 | } | |
398 | ||
399 | if (m_elision) { | |
400 | RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length)); | |
401 | generator.emitPutById(array.get(), generator.propertyNames().length, value); | |
402 | } | |
403 | ||
404 | return generator.moveToDestinationIfNeeded(dst, array.get()); | |
405 | } | |
406 | ||
407 | // ------------------------------ PropertyNode ---------------------------- | |
408 | ||
409 | PropertyNode::~PropertyNode() | |
410 | { | |
411 | NodeReleaser::releaseAllNodes(this); | |
412 | } | |
413 | ||
414 | void PropertyNode::releaseNodes(NodeReleaser& releaser) | |
415 | { | |
416 | releaser.release(m_assign); | |
417 | } | |
418 | ||
419 | // ------------------------------ ObjectLiteralNode ---------------------------- | |
420 | ||
421 | ObjectLiteralNode::~ObjectLiteralNode() | |
422 | { | |
423 | NodeReleaser::releaseAllNodes(this); | |
424 | } | |
425 | ||
426 | void ObjectLiteralNode::releaseNodes(NodeReleaser& releaser) | |
427 | { | |
428 | releaser.release(m_list); | |
429 | } | |
430 | ||
431 | RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
432 | { | |
433 | if (!m_list) { | |
434 | if (dst == generator.ignoredResult()) | |
435 | return 0; | |
436 | return generator.emitNewObject(generator.finalDestination(dst)); | |
437 | } | |
438 | return generator.emitNode(dst, m_list.get()); | |
439 | } | |
440 | ||
441 | // ------------------------------ PropertyListNode ----------------------------- | |
442 | ||
443 | PropertyListNode::~PropertyListNode() | |
444 | { | |
445 | NodeReleaser::releaseAllNodes(this); | |
446 | } | |
447 | ||
448 | void PropertyListNode::releaseNodes(NodeReleaser& releaser) | |
449 | { | |
450 | releaser.release(m_node); | |
451 | releaser.release(m_next); | |
452 | } | |
453 | ||
454 | RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
455 | { | |
456 | RefPtr<RegisterID> newObj = generator.tempDestination(dst); | |
457 | ||
458 | generator.emitNewObject(newObj.get()); | |
459 | ||
460 | for (PropertyListNode* p = this; p; p = p->m_next.get()) { | |
461 | RegisterID* value = generator.emitNode(p->m_node->m_assign.get()); | |
462 | ||
463 | switch (p->m_node->m_type) { | |
464 | case PropertyNode::Constant: { | |
465 | generator.emitPutById(newObj.get(), p->m_node->name(), value); | |
466 | break; | |
467 | } | |
468 | case PropertyNode::Getter: { | |
469 | generator.emitPutGetter(newObj.get(), p->m_node->name(), value); | |
470 | break; | |
471 | } | |
472 | case PropertyNode::Setter: { | |
473 | generator.emitPutSetter(newObj.get(), p->m_node->name(), value); | |
474 | break; | |
475 | } | |
476 | default: | |
477 | ASSERT_NOT_REACHED(); | |
478 | } | |
479 | } | |
480 | ||
481 | return generator.moveToDestinationIfNeeded(dst, newObj.get()); | |
482 | } | |
483 | ||
484 | // ------------------------------ BracketAccessorNode -------------------------------- | |
485 | ||
486 | BracketAccessorNode::~BracketAccessorNode() | |
487 | { | |
488 | NodeReleaser::releaseAllNodes(this); | |
489 | } | |
490 | ||
491 | void BracketAccessorNode::releaseNodes(NodeReleaser& releaser) | |
492 | { | |
493 | releaser.release(m_base); | |
494 | releaser.release(m_subscript); | |
495 | } | |
496 | ||
497 | RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
498 | { | |
499 | RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments, m_subscript->isPure(generator)); | |
500 | RegisterID* property = generator.emitNode(m_subscript.get()); | |
501 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
502 | return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); | |
503 | } | |
504 | ||
505 | // ------------------------------ DotAccessorNode -------------------------------- | |
506 | ||
507 | DotAccessorNode::~DotAccessorNode() | |
508 | { | |
509 | NodeReleaser::releaseAllNodes(this); | |
510 | } | |
511 | ||
512 | void DotAccessorNode::releaseNodes(NodeReleaser& releaser) | |
513 | { | |
514 | releaser.release(m_base); | |
515 | } | |
516 | ||
517 | RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
518 | { | |
519 | RegisterID* base = generator.emitNode(m_base.get()); | |
520 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
521 | return generator.emitGetById(generator.finalDestination(dst), base, m_ident); | |
522 | } | |
523 | ||
524 | // ------------------------------ ArgumentListNode ----------------------------- | |
525 | ||
526 | ArgumentListNode::~ArgumentListNode() | |
527 | { | |
528 | NodeReleaser::releaseAllNodes(this); | |
529 | } | |
530 | ||
531 | void ArgumentListNode::releaseNodes(NodeReleaser& releaser) | |
532 | { | |
533 | releaser.release(m_next); | |
534 | releaser.release(m_expr); | |
535 | } | |
536 | ||
537 | RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
538 | { | |
539 | ASSERT(m_expr); | |
540 | return generator.emitNode(dst, m_expr.get()); | |
541 | } | |
542 | ||
543 | // ------------------------------ ArgumentsNode ----------------------------- | |
544 | ||
545 | ArgumentsNode::~ArgumentsNode() | |
546 | { | |
547 | NodeReleaser::releaseAllNodes(this); | |
548 | } | |
549 | ||
550 | void ArgumentsNode::releaseNodes(NodeReleaser& releaser) | |
551 | { | |
552 | releaser.release(m_listNode); | |
553 | } | |
554 | ||
555 | // ------------------------------ NewExprNode ---------------------------------- | |
556 | ||
557 | NewExprNode::~NewExprNode() | |
558 | { | |
559 | NodeReleaser::releaseAllNodes(this); | |
560 | } | |
561 | ||
562 | void NewExprNode::releaseNodes(NodeReleaser& releaser) | |
563 | { | |
564 | releaser.release(m_expr); | |
565 | releaser.release(m_args); | |
566 | } | |
567 | ||
568 | RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
569 | { | |
570 | RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); | |
571 | return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
572 | } | |
573 | ||
574 | // ------------------------------ EvalFunctionCallNode ---------------------------------- | |
575 | ||
576 | EvalFunctionCallNode::~EvalFunctionCallNode() | |
577 | { | |
578 | NodeReleaser::releaseAllNodes(this); | |
579 | } | |
580 | ||
581 | void EvalFunctionCallNode::releaseNodes(NodeReleaser& releaser) | |
582 | { | |
583 | releaser.release(m_args); | |
584 | } | |
585 | ||
586 | RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
587 | { | |
588 | RefPtr<RegisterID> func = generator.tempDestination(dst); | |
589 | RefPtr<RegisterID> thisRegister = generator.newTemporary(); | |
590 | generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); | |
591 | generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval); | |
592 | return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
593 | } | |
594 | ||
595 | // ------------------------------ FunctionCallValueNode ---------------------------------- | |
596 | ||
597 | FunctionCallValueNode::~FunctionCallValueNode() | |
598 | { | |
599 | NodeReleaser::releaseAllNodes(this); | |
600 | } | |
601 | ||
602 | void FunctionCallValueNode::releaseNodes(NodeReleaser& releaser) | |
603 | { | |
604 | releaser.release(m_expr); | |
605 | releaser.release(m_args); | |
606 | } | |
607 | ||
608 | RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
609 | { | |
610 | RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); | |
611 | RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); | |
612 | return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
613 | } | |
614 | ||
615 | // ------------------------------ FunctionCallResolveNode ---------------------------------- | |
616 | ||
617 | FunctionCallResolveNode::~FunctionCallResolveNode() | |
618 | { | |
619 | NodeReleaser::releaseAllNodes(this); | |
620 | } | |
621 | ||
622 | void FunctionCallResolveNode::releaseNodes(NodeReleaser& releaser) | |
623 | { | |
624 | releaser.release(m_args); | |
625 | } | |
626 | ||
627 | RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
628 | { | |
629 | if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { | |
630 | RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); | |
631 | return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
632 | } | |
633 | ||
634 | int index = 0; | |
635 | size_t depth = 0; | |
636 | JSObject* globalObject = 0; | |
637 | if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { | |
638 | RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); | |
639 | RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); | |
640 | return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
641 | } | |
642 | ||
643 | RefPtr<RegisterID> func = generator.tempDestination(dst); | |
644 | RefPtr<RegisterID> thisRegister = generator.newTemporary(); | |
645 | int identifierStart = divot() - startOffset(); | |
646 | generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); | |
647 | generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident); | |
648 | return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
649 | } | |
650 | ||
651 | // ------------------------------ FunctionCallBracketNode ---------------------------------- | |
652 | ||
653 | FunctionCallBracketNode::~FunctionCallBracketNode() | |
654 | { | |
655 | NodeReleaser::releaseAllNodes(this); | |
656 | } | |
657 | ||
658 | void FunctionCallBracketNode::releaseNodes(NodeReleaser& releaser) | |
659 | { | |
660 | releaser.release(m_base); | |
661 | releaser.release(m_subscript); | |
662 | releaser.release(m_args); | |
663 | } | |
664 | ||
665 | RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
666 | { | |
667 | RefPtr<RegisterID> base = generator.emitNode(m_base.get()); | |
668 | RegisterID* property = generator.emitNode(m_subscript.get()); | |
669 | generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); | |
670 | RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); | |
671 | RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); | |
672 | return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
673 | } | |
674 | ||
675 | // ------------------------------ FunctionCallDotNode ---------------------------------- | |
676 | ||
677 | FunctionCallDotNode::~FunctionCallDotNode() | |
678 | { | |
679 | NodeReleaser::releaseAllNodes(this); | |
680 | } | |
681 | ||
682 | void FunctionCallDotNode::releaseNodes(NodeReleaser& releaser) | |
683 | { | |
684 | releaser.release(m_base); | |
685 | releaser.release(m_args); | |
686 | } | |
687 | ||
688 | RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
689 | { | |
690 | RefPtr<RegisterID> base = generator.emitNode(m_base.get()); | |
691 | generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); | |
692 | RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); | |
693 | RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); | |
694 | return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); | |
695 | } | |
696 | ||
697 | // ------------------------------ PostfixResolveNode ---------------------------------- | |
698 | ||
699 | static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper) | |
700 | { | |
701 | return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst); | |
702 | } | |
703 | ||
704 | static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) | |
705 | { | |
706 | return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst); | |
707 | } | |
708 | ||
709 | RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
710 | { | |
711 | if (RegisterID* local = generator.registerFor(m_ident)) { | |
712 | if (generator.isLocalConstant(m_ident)) { | |
713 | if (dst == generator.ignoredResult()) | |
714 | return 0; | |
715 | return generator.emitToJSNumber(generator.finalDestination(dst), local); | |
716 | } | |
717 | ||
718 | if (dst == generator.ignoredResult()) | |
719 | return emitPreIncOrDec(generator, local, m_operator); | |
720 | return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator); | |
721 | } | |
722 | ||
723 | int index = 0; | |
724 | size_t depth = 0; | |
725 | JSObject* globalObject = 0; | |
726 | if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { | |
727 | RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); | |
728 | RegisterID* oldValue; | |
729 | if (dst == generator.ignoredResult()) { | |
730 | oldValue = 0; | |
731 | emitPreIncOrDec(generator, value.get(), m_operator); | |
732 | } else { | |
733 | oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); | |
734 | } | |
735 | generator.emitPutScopedVar(depth, index, value.get(), globalObject); | |
736 | return oldValue; | |
737 | } | |
738 | ||
739 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
740 | RefPtr<RegisterID> value = generator.newTemporary(); | |
741 | RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident); | |
742 | RegisterID* oldValue; | |
743 | if (dst == generator.ignoredResult()) { | |
744 | oldValue = 0; | |
745 | emitPreIncOrDec(generator, value.get(), m_operator); | |
746 | } else { | |
747 | oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); | |
748 | } | |
749 | generator.emitPutById(base.get(), m_ident, value.get()); | |
750 | return oldValue; | |
751 | } | |
752 | ||
753 | // ------------------------------ PostfixBracketNode ---------------------------------- | |
754 | ||
755 | PostfixBracketNode::~PostfixBracketNode() | |
756 | { | |
757 | NodeReleaser::releaseAllNodes(this); | |
758 | } | |
759 | ||
760 | void PostfixBracketNode::releaseNodes(NodeReleaser& releaser) | |
761 | { | |
762 | releaser.release(m_base); | |
763 | releaser.release(m_subscript); | |
764 | } | |
765 | ||
766 | RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
767 | { | |
768 | RefPtr<RegisterID> base = generator.emitNode(m_base.get()); | |
769 | RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); | |
770 | ||
771 | generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); | |
772 | RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); | |
773 | RegisterID* oldValue; | |
774 | if (dst == generator.ignoredResult()) { | |
775 | oldValue = 0; | |
776 | if (m_operator == OpPlusPlus) | |
777 | generator.emitPreInc(value.get()); | |
778 | else | |
779 | generator.emitPreDec(value.get()); | |
780 | } else { | |
781 | oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); | |
782 | } | |
783 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
784 | generator.emitPutByVal(base.get(), property.get(), value.get()); | |
785 | return oldValue; | |
786 | } | |
787 | ||
788 | // ------------------------------ PostfixDotNode ---------------------------------- | |
789 | ||
790 | PostfixDotNode::~PostfixDotNode() | |
791 | { | |
792 | NodeReleaser::releaseAllNodes(this); | |
793 | } | |
794 | ||
795 | void PostfixDotNode::releaseNodes(NodeReleaser& releaser) | |
796 | { | |
797 | releaser.release(m_base); | |
798 | } | |
799 | ||
800 | RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
801 | { | |
802 | RefPtr<RegisterID> base = generator.emitNode(m_base.get()); | |
803 | ||
804 | generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); | |
805 | RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); | |
806 | RegisterID* oldValue; | |
807 | if (dst == generator.ignoredResult()) { | |
808 | oldValue = 0; | |
809 | if (m_operator == OpPlusPlus) | |
810 | generator.emitPreInc(value.get()); | |
811 | else | |
812 | generator.emitPreDec(value.get()); | |
813 | } else { | |
814 | oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); | |
815 | } | |
816 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
817 | generator.emitPutById(base.get(), m_ident, value.get()); | |
818 | return oldValue; | |
819 | } | |
820 | ||
821 | // ------------------------------ PostfixErrorNode ----------------------------------- | |
822 | ||
823 | PostfixErrorNode::~PostfixErrorNode() | |
824 | { | |
825 | NodeReleaser::releaseAllNodes(this); | |
826 | } | |
827 | ||
828 | void PostfixErrorNode::releaseNodes(NodeReleaser& releaser) | |
829 | { | |
830 | releaser.release(m_expr); | |
831 | } | |
832 | ||
833 | RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
834 | { | |
835 | return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Postfix ++ operator applied to value that is not a reference." : "Postfix -- operator applied to value that is not a reference."); | |
836 | } | |
837 | ||
838 | // ------------------------------ DeleteResolveNode ----------------------------------- | |
839 | ||
840 | RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
841 | { | |
842 | if (generator.registerFor(m_ident)) | |
843 | return generator.emitUnexpectedLoad(generator.finalDestination(dst), false); | |
844 | ||
845 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
846 | RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident); | |
847 | return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident); | |
848 | } | |
849 | ||
850 | // ------------------------------ DeleteBracketNode ----------------------------------- | |
851 | ||
852 | DeleteBracketNode::~DeleteBracketNode() | |
853 | { | |
854 | NodeReleaser::releaseAllNodes(this); | |
855 | } | |
856 | ||
857 | void DeleteBracketNode::releaseNodes(NodeReleaser& releaser) | |
858 | { | |
859 | releaser.release(m_base); | |
860 | releaser.release(m_subscript); | |
861 | } | |
862 | ||
863 | RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
864 | { | |
865 | RefPtr<RegisterID> r0 = generator.emitNode(m_base.get()); | |
866 | RegisterID* r1 = generator.emitNode(m_subscript.get()); | |
867 | ||
868 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
869 | return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); | |
870 | } | |
871 | ||
872 | // ------------------------------ DeleteDotNode ----------------------------------- | |
873 | ||
874 | DeleteDotNode::~DeleteDotNode() | |
875 | { | |
876 | NodeReleaser::releaseAllNodes(this); | |
877 | } | |
878 | ||
879 | void DeleteDotNode::releaseNodes(NodeReleaser& releaser) | |
880 | { | |
881 | releaser.release(m_base); | |
882 | } | |
883 | ||
884 | RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
885 | { | |
886 | RegisterID* r0 = generator.emitNode(m_base.get()); | |
887 | ||
888 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
889 | return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); | |
890 | } | |
891 | ||
892 | // ------------------------------ DeleteValueNode ----------------------------------- | |
893 | ||
894 | DeleteValueNode::~DeleteValueNode() | |
895 | { | |
896 | NodeReleaser::releaseAllNodes(this); | |
897 | } | |
898 | ||
899 | void DeleteValueNode::releaseNodes(NodeReleaser& releaser) | |
900 | { | |
901 | releaser.release(m_expr); | |
902 | } | |
903 | ||
904 | RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
905 | { | |
906 | generator.emitNode(generator.ignoredResult(), m_expr.get()); | |
907 | ||
908 | // delete on a non-location expression ignores the value and returns true | |
909 | return generator.emitUnexpectedLoad(generator.finalDestination(dst), true); | |
910 | } | |
911 | ||
912 | // ------------------------------ VoidNode ------------------------------------- | |
913 | ||
914 | VoidNode::~VoidNode() | |
915 | { | |
916 | NodeReleaser::releaseAllNodes(this); | |
917 | } | |
918 | ||
919 | void VoidNode::releaseNodes(NodeReleaser& releaser) | |
920 | { | |
921 | releaser.release(m_expr); | |
922 | } | |
923 | ||
924 | RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
925 | { | |
926 | if (dst == generator.ignoredResult()) { | |
927 | generator.emitNode(generator.ignoredResult(), m_expr.get()); | |
928 | return 0; | |
929 | } | |
930 | RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); | |
931 | return generator.emitLoad(dst, jsUndefined()); | |
932 | } | |
933 | ||
934 | // ------------------------------ TypeOfValueNode ----------------------------------- | |
935 | ||
936 | RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
937 | { | |
938 | if (RegisterID* local = generator.registerFor(m_ident)) { | |
939 | if (dst == generator.ignoredResult()) | |
940 | return 0; | |
941 | return generator.emitTypeOf(generator.finalDestination(dst), local); | |
942 | } | |
943 | ||
944 | RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident); | |
945 | generator.emitGetById(scratch.get(), scratch.get(), m_ident); | |
946 | if (dst == generator.ignoredResult()) | |
947 | return 0; | |
948 | return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get()); | |
949 | } | |
950 | ||
951 | // ------------------------------ TypeOfValueNode ----------------------------------- | |
952 | ||
953 | TypeOfValueNode::~TypeOfValueNode() | |
954 | { | |
955 | NodeReleaser::releaseAllNodes(this); | |
956 | } | |
957 | ||
958 | void TypeOfValueNode::releaseNodes(NodeReleaser& releaser) | |
959 | { | |
960 | releaser.release(m_expr); | |
961 | } | |
962 | ||
963 | RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
964 | { | |
965 | if (dst == generator.ignoredResult()) { | |
966 | generator.emitNode(generator.ignoredResult(), m_expr.get()); | |
967 | return 0; | |
968 | } | |
969 | RefPtr<RegisterID> src = generator.emitNode(m_expr.get()); | |
970 | return generator.emitTypeOf(generator.finalDestination(dst), src.get()); | |
971 | } | |
972 | ||
973 | // ------------------------------ PrefixResolveNode ---------------------------------- | |
974 | ||
975 | RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
976 | { | |
977 | if (RegisterID* local = generator.registerFor(m_ident)) { | |
978 | if (generator.isLocalConstant(m_ident)) { | |
979 | if (dst == generator.ignoredResult()) | |
980 | return 0; | |
981 | RefPtr<RegisterID> r0 = generator.emitUnexpectedLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0); | |
982 | return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes()); | |
983 | } | |
984 | ||
985 | emitPreIncOrDec(generator, local, m_operator); | |
986 | return generator.moveToDestinationIfNeeded(dst, local); | |
987 | } | |
988 | ||
989 | int index = 0; | |
990 | size_t depth = 0; | |
991 | JSObject* globalObject = 0; | |
992 | if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { | |
993 | RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); | |
994 | emitPreIncOrDec(generator, propDst.get(), m_operator); | |
995 | generator.emitPutScopedVar(depth, index, propDst.get(), globalObject); | |
996 | return generator.moveToDestinationIfNeeded(dst, propDst.get()); | |
997 | } | |
998 | ||
999 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1000 | RefPtr<RegisterID> propDst = generator.tempDestination(dst); | |
1001 | RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident); | |
1002 | emitPreIncOrDec(generator, propDst.get(), m_operator); | |
1003 | generator.emitPutById(base.get(), m_ident, propDst.get()); | |
1004 | return generator.moveToDestinationIfNeeded(dst, propDst.get()); | |
1005 | } | |
1006 | ||
1007 | // ------------------------------ PrefixBracketNode ---------------------------------- | |
1008 | ||
1009 | PrefixBracketNode::~PrefixBracketNode() | |
1010 | { | |
1011 | NodeReleaser::releaseAllNodes(this); | |
1012 | } | |
1013 | ||
1014 | void PrefixBracketNode::releaseNodes(NodeReleaser& releaser) | |
1015 | { | |
1016 | releaser.release(m_base); | |
1017 | releaser.release(m_subscript); | |
1018 | } | |
1019 | ||
1020 | RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1021 | { | |
1022 | RefPtr<RegisterID> base = generator.emitNode(m_base.get()); | |
1023 | RefPtr<RegisterID> property = generator.emitNode(m_subscript.get()); | |
1024 | RefPtr<RegisterID> propDst = generator.tempDestination(dst); | |
1025 | ||
1026 | generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); | |
1027 | RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get()); | |
1028 | if (m_operator == OpPlusPlus) | |
1029 | generator.emitPreInc(value); | |
1030 | else | |
1031 | generator.emitPreDec(value); | |
1032 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1033 | generator.emitPutByVal(base.get(), property.get(), value); | |
1034 | return generator.moveToDestinationIfNeeded(dst, propDst.get()); | |
1035 | } | |
1036 | ||
1037 | // ------------------------------ PrefixDotNode ---------------------------------- | |
1038 | ||
1039 | PrefixDotNode::~PrefixDotNode() | |
1040 | { | |
1041 | NodeReleaser::releaseAllNodes(this); | |
1042 | } | |
1043 | ||
1044 | void PrefixDotNode::releaseNodes(NodeReleaser& releaser) | |
1045 | { | |
1046 | releaser.release(m_base); | |
1047 | } | |
1048 | ||
1049 | RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1050 | { | |
1051 | RefPtr<RegisterID> base = generator.emitNode(m_base.get()); | |
1052 | RefPtr<RegisterID> propDst = generator.tempDestination(dst); | |
1053 | ||
1054 | generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); | |
1055 | RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident); | |
1056 | if (m_operator == OpPlusPlus) | |
1057 | generator.emitPreInc(value); | |
1058 | else | |
1059 | generator.emitPreDec(value); | |
1060 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1061 | generator.emitPutById(base.get(), m_ident, value); | |
1062 | return generator.moveToDestinationIfNeeded(dst, propDst.get()); | |
1063 | } | |
1064 | ||
1065 | // ------------------------------ PrefixErrorNode ----------------------------------- | |
1066 | ||
1067 | PrefixErrorNode::~PrefixErrorNode() | |
1068 | { | |
1069 | NodeReleaser::releaseAllNodes(this); | |
1070 | } | |
1071 | ||
1072 | void PrefixErrorNode::releaseNodes(NodeReleaser& releaser) | |
1073 | { | |
1074 | releaser.release(m_expr); | |
1075 | } | |
1076 | ||
1077 | RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
1078 | { | |
1079 | return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus ? "Prefix ++ operator applied to value that is not a reference." : "Prefix -- operator applied to value that is not a reference."); | |
1080 | } | |
1081 | ||
1082 | // ------------------------------ Unary Operation Nodes ----------------------------------- | |
1083 | ||
1084 | UnaryOpNode::~UnaryOpNode() | |
1085 | { | |
1086 | NodeReleaser::releaseAllNodes(this); | |
1087 | } | |
1088 | ||
1089 | void UnaryOpNode::releaseNodes(NodeReleaser& releaser) | |
1090 | { | |
1091 | releaser.release(m_expr); | |
1092 | } | |
1093 | ||
1094 | RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1095 | { | |
1096 | RegisterID* src = generator.emitNode(m_expr.get()); | |
1097 | return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); | |
1098 | } | |
1099 | ||
1100 | // ------------------------------ Binary Operation Nodes ----------------------------------- | |
1101 | ||
1102 | BinaryOpNode::~BinaryOpNode() | |
1103 | { | |
1104 | NodeReleaser::releaseAllNodes(this); | |
1105 | } | |
1106 | ||
1107 | void BinaryOpNode::releaseNodes(NodeReleaser& releaser) | |
1108 | { | |
1109 | releaser.release(m_expr1); | |
1110 | releaser.release(m_expr2); | |
1111 | } | |
1112 | ||
1113 | RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1114 | { | |
1115 | OpcodeID opcodeID = this->opcodeID(); | |
1116 | if (opcodeID == op_neq) { | |
1117 | if (m_expr1->isNull() || m_expr2->isNull()) { | |
1118 | RefPtr<RegisterID> src = generator.tempDestination(dst); | |
1119 | generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); | |
1120 | return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); | |
1121 | } | |
1122 | } | |
1123 | ||
1124 | RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); | |
1125 | RegisterID* src2 = generator.emitNode(m_expr2.get()); | |
1126 | return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); | |
1127 | } | |
1128 | ||
1129 | RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1130 | { | |
1131 | if (m_expr1->isNull() || m_expr2->isNull()) { | |
1132 | RefPtr<RegisterID> src = generator.tempDestination(dst); | |
1133 | generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2.get() : m_expr1.get()); | |
1134 | return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); | |
1135 | } | |
1136 | ||
1137 | RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); | |
1138 | RegisterID* src2 = generator.emitNode(m_expr2.get()); | |
1139 | return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); | |
1140 | } | |
1141 | ||
1142 | RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1143 | { | |
1144 | RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); | |
1145 | RegisterID* src2 = generator.emitNode(m_expr2.get()); | |
1146 | return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); | |
1147 | } | |
1148 | ||
1149 | RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1150 | { | |
1151 | RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); | |
1152 | RegisterID* src2 = generator.emitNode(m_expr2.get()); | |
1153 | return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); | |
1154 | } | |
1155 | ||
1156 | RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1157 | { | |
1158 | RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); | |
1159 | RegisterID* src2 = generator.emitNode(m_expr2.get()); | |
1160 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1161 | return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); | |
1162 | } | |
1163 | ||
1164 | RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1165 | { | |
1166 | RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1.get(), m_rightHasAssignments, m_expr2->isPure(generator)); | |
1167 | RefPtr<RegisterID> src2 = generator.emitNode(m_expr2.get()); | |
1168 | ||
1169 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1170 | generator.emitGetByIdExceptionInfo(op_instanceof); | |
1171 | RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype); | |
1172 | ||
1173 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1174 | return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype); | |
1175 | } | |
1176 | ||
1177 | // ------------------------------ LogicalOpNode ---------------------------- | |
1178 | ||
1179 | LogicalOpNode::~LogicalOpNode() | |
1180 | { | |
1181 | NodeReleaser::releaseAllNodes(this); | |
1182 | } | |
1183 | ||
1184 | void LogicalOpNode::releaseNodes(NodeReleaser& releaser) | |
1185 | { | |
1186 | releaser.release(m_expr1); | |
1187 | releaser.release(m_expr2); | |
1188 | } | |
1189 | ||
1190 | RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1191 | { | |
1192 | RefPtr<RegisterID> temp = generator.tempDestination(dst); | |
1193 | RefPtr<Label> target = generator.newLabel(); | |
1194 | ||
1195 | generator.emitNode(temp.get(), m_expr1.get()); | |
1196 | if (m_operator == OpLogicalAnd) | |
1197 | generator.emitJumpIfFalse(temp.get(), target.get()); | |
1198 | else | |
1199 | generator.emitJumpIfTrue(temp.get(), target.get()); | |
1200 | generator.emitNode(temp.get(), m_expr2.get()); | |
1201 | generator.emitLabel(target.get()); | |
1202 | ||
1203 | return generator.moveToDestinationIfNeeded(dst, temp.get()); | |
1204 | } | |
1205 | ||
1206 | // ------------------------------ ConditionalNode ------------------------------ | |
1207 | ||
1208 | ConditionalNode::~ConditionalNode() | |
1209 | { | |
1210 | NodeReleaser::releaseAllNodes(this); | |
1211 | } | |
1212 | ||
1213 | void ConditionalNode::releaseNodes(NodeReleaser& releaser) | |
1214 | { | |
1215 | releaser.release(m_logical); | |
1216 | releaser.release(m_expr1); | |
1217 | releaser.release(m_expr2); | |
1218 | } | |
1219 | ||
1220 | RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1221 | { | |
1222 | RefPtr<RegisterID> newDst = generator.finalDestination(dst); | |
1223 | RefPtr<Label> beforeElse = generator.newLabel(); | |
1224 | RefPtr<Label> afterElse = generator.newLabel(); | |
1225 | ||
1226 | RegisterID* cond = generator.emitNode(m_logical.get()); | |
1227 | generator.emitJumpIfFalse(cond, beforeElse.get()); | |
1228 | ||
1229 | generator.emitNode(newDst.get(), m_expr1.get()); | |
1230 | generator.emitJump(afterElse.get()); | |
1231 | ||
1232 | generator.emitLabel(beforeElse.get()); | |
1233 | generator.emitNode(newDst.get(), m_expr2.get()); | |
1234 | ||
1235 | generator.emitLabel(afterElse.get()); | |
1236 | ||
1237 | return newDst.get(); | |
1238 | } | |
1239 | ||
1240 | // ------------------------------ ReadModifyResolveNode ----------------------------------- | |
1241 | ||
1242 | ReadModifyResolveNode::~ReadModifyResolveNode() | |
1243 | { | |
1244 | NodeReleaser::releaseAllNodes(this); | |
1245 | } | |
1246 | ||
1247 | void ReadModifyResolveNode::releaseNodes(NodeReleaser& releaser) | |
1248 | { | |
1249 | releaser.release(m_right); | |
1250 | } | |
1251 | ||
1252 | // FIXME: should this be moved to be a method on BytecodeGenerator? | |
1253 | static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, RegisterID* src2, Operator oper, OperandTypes types) | |
1254 | { | |
1255 | OpcodeID opcodeID; | |
1256 | switch (oper) { | |
1257 | case OpMultEq: | |
1258 | opcodeID = op_mul; | |
1259 | break; | |
1260 | case OpDivEq: | |
1261 | opcodeID = op_div; | |
1262 | break; | |
1263 | case OpPlusEq: | |
1264 | opcodeID = op_add; | |
1265 | break; | |
1266 | case OpMinusEq: | |
1267 | opcodeID = op_sub; | |
1268 | break; | |
1269 | case OpLShift: | |
1270 | opcodeID = op_lshift; | |
1271 | break; | |
1272 | case OpRShift: | |
1273 | opcodeID = op_rshift; | |
1274 | break; | |
1275 | case OpURShift: | |
1276 | opcodeID = op_urshift; | |
1277 | break; | |
1278 | case OpAndEq: | |
1279 | opcodeID = op_bitand; | |
1280 | break; | |
1281 | case OpXOrEq: | |
1282 | opcodeID = op_bitxor; | |
1283 | break; | |
1284 | case OpOrEq: | |
1285 | opcodeID = op_bitor; | |
1286 | break; | |
1287 | case OpModEq: | |
1288 | opcodeID = op_mod; | |
1289 | break; | |
1290 | default: | |
1291 | ASSERT_NOT_REACHED(); | |
1292 | return dst; | |
1293 | } | |
1294 | ||
1295 | return generator.emitBinaryOp(opcodeID, dst, src1, src2, types); | |
1296 | } | |
1297 | ||
1298 | RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1299 | { | |
1300 | if (RegisterID* local = generator.registerFor(m_ident)) { | |
1301 | if (generator.isLocalConstant(m_ident)) { | |
1302 | RegisterID* src2 = generator.emitNode(m_right.get()); | |
1303 | return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); | |
1304 | } | |
1305 | ||
1306 | if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { | |
1307 | RefPtr<RegisterID> result = generator.newTemporary(); | |
1308 | generator.emitMove(result.get(), local); | |
1309 | RegisterID* src2 = generator.emitNode(m_right.get()); | |
1310 | emitReadModifyAssignment(generator, result.get(), result.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); | |
1311 | generator.emitMove(local, result.get()); | |
1312 | return generator.moveToDestinationIfNeeded(dst, result.get()); | |
1313 | } | |
1314 | ||
1315 | RegisterID* src2 = generator.emitNode(m_right.get()); | |
1316 | RegisterID* result = emitReadModifyAssignment(generator, local, local, src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); | |
1317 | return generator.moveToDestinationIfNeeded(dst, result); | |
1318 | } | |
1319 | ||
1320 | int index = 0; | |
1321 | size_t depth = 0; | |
1322 | JSObject* globalObject = 0; | |
1323 | if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { | |
1324 | RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); | |
1325 | RegisterID* src2 = generator.emitNode(m_right.get()); | |
1326 | RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); | |
1327 | generator.emitPutScopedVar(depth, index, result, globalObject); | |
1328 | return result; | |
1329 | } | |
1330 | ||
1331 | RefPtr<RegisterID> src1 = generator.tempDestination(dst); | |
1332 | generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0); | |
1333 | RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); | |
1334 | RegisterID* src2 = generator.emitNode(m_right.get()); | |
1335 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1336 | RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); | |
1337 | return generator.emitPutById(base.get(), m_ident, result); | |
1338 | } | |
1339 | ||
1340 | // ------------------------------ AssignResolveNode ----------------------------------- | |
1341 | ||
1342 | AssignResolveNode::~AssignResolveNode() | |
1343 | { | |
1344 | NodeReleaser::releaseAllNodes(this); | |
1345 | } | |
1346 | ||
1347 | void AssignResolveNode::releaseNodes(NodeReleaser& releaser) | |
1348 | { | |
1349 | releaser.release(m_right); | |
1350 | } | |
1351 | ||
1352 | RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1353 | { | |
1354 | if (RegisterID* local = generator.registerFor(m_ident)) { | |
1355 | if (generator.isLocalConstant(m_ident)) | |
1356 | return generator.emitNode(dst, m_right.get()); | |
1357 | ||
1358 | RegisterID* result = generator.emitNode(local, m_right.get()); | |
1359 | return generator.moveToDestinationIfNeeded(dst, result); | |
1360 | } | |
1361 | ||
1362 | int index = 0; | |
1363 | size_t depth = 0; | |
1364 | JSObject* globalObject = 0; | |
1365 | if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { | |
1366 | if (dst == generator.ignoredResult()) | |
1367 | dst = 0; | |
1368 | RegisterID* value = generator.emitNode(dst, m_right.get()); | |
1369 | generator.emitPutScopedVar(depth, index, value, globalObject); | |
1370 | return value; | |
1371 | } | |
1372 | ||
1373 | RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); | |
1374 | if (dst == generator.ignoredResult()) | |
1375 | dst = 0; | |
1376 | RegisterID* value = generator.emitNode(dst, m_right.get()); | |
1377 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1378 | return generator.emitPutById(base.get(), m_ident, value); | |
1379 | } | |
1380 | ||
1381 | // ------------------------------ AssignDotNode ----------------------------------- | |
1382 | ||
1383 | AssignDotNode::~AssignDotNode() | |
1384 | { | |
1385 | NodeReleaser::releaseAllNodes(this); | |
1386 | } | |
1387 | ||
1388 | void AssignDotNode::releaseNodes(NodeReleaser& releaser) | |
1389 | { | |
1390 | releaser.release(m_base); | |
1391 | releaser.release(m_right); | |
1392 | } | |
1393 | ||
1394 | RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1395 | { | |
1396 | RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); | |
1397 | RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); | |
1398 | RegisterID* result = generator.emitNode(value.get(), m_right.get()); | |
1399 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1400 | generator.emitPutById(base.get(), m_ident, result); | |
1401 | return generator.moveToDestinationIfNeeded(dst, result); | |
1402 | } | |
1403 | ||
1404 | // ------------------------------ ReadModifyDotNode ----------------------------------- | |
1405 | ||
1406 | ReadModifyDotNode::~ReadModifyDotNode() | |
1407 | { | |
1408 | NodeReleaser::releaseAllNodes(this); | |
1409 | } | |
1410 | ||
1411 | void ReadModifyDotNode::releaseNodes(NodeReleaser& releaser) | |
1412 | { | |
1413 | releaser.release(m_base); | |
1414 | releaser.release(m_right); | |
1415 | } | |
1416 | ||
1417 | RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1418 | { | |
1419 | RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_rightHasAssignments, m_right->isPure(generator)); | |
1420 | ||
1421 | generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); | |
1422 | RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); | |
1423 | RegisterID* change = generator.emitNode(m_right.get()); | |
1424 | RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); | |
1425 | ||
1426 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1427 | return generator.emitPutById(base.get(), m_ident, updatedValue); | |
1428 | } | |
1429 | ||
1430 | // ------------------------------ AssignErrorNode ----------------------------------- | |
1431 | ||
1432 | AssignErrorNode::~AssignErrorNode() | |
1433 | { | |
1434 | NodeReleaser::releaseAllNodes(this); | |
1435 | } | |
1436 | ||
1437 | void AssignErrorNode::releaseNodes(NodeReleaser& releaser) | |
1438 | { | |
1439 | releaser.release(m_left); | |
1440 | releaser.release(m_right); | |
1441 | } | |
1442 | ||
1443 | RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
1444 | { | |
1445 | return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference."); | |
1446 | } | |
1447 | ||
1448 | // ------------------------------ AssignBracketNode ----------------------------------- | |
1449 | ||
1450 | AssignBracketNode::~AssignBracketNode() | |
1451 | { | |
1452 | NodeReleaser::releaseAllNodes(this); | |
1453 | } | |
1454 | ||
1455 | void AssignBracketNode::releaseNodes(NodeReleaser& releaser) | |
1456 | { | |
1457 | releaser.release(m_base); | |
1458 | releaser.release(m_subscript); | |
1459 | releaser.release(m_right); | |
1460 | } | |
1461 | ||
1462 | RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1463 | { | |
1464 | RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); | |
1465 | RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); | |
1466 | RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); | |
1467 | RegisterID* result = generator.emitNode(value.get(), m_right.get()); | |
1468 | ||
1469 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1470 | generator.emitPutByVal(base.get(), property.get(), result); | |
1471 | return generator.moveToDestinationIfNeeded(dst, result); | |
1472 | } | |
1473 | ||
1474 | // ------------------------------ ReadModifyBracketNode ----------------------------------- | |
1475 | ||
1476 | ReadModifyBracketNode::~ReadModifyBracketNode() | |
1477 | { | |
1478 | NodeReleaser::releaseAllNodes(this); | |
1479 | } | |
1480 | ||
1481 | void ReadModifyBracketNode::releaseNodes(NodeReleaser& releaser) | |
1482 | { | |
1483 | releaser.release(m_base); | |
1484 | releaser.release(m_subscript); | |
1485 | releaser.release(m_right); | |
1486 | } | |
1487 | ||
1488 | RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1489 | { | |
1490 | RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base.get(), m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); | |
1491 | RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript.get(), m_rightHasAssignments, m_right->isPure(generator)); | |
1492 | ||
1493 | generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); | |
1494 | RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); | |
1495 | RegisterID* change = generator.emitNode(m_right.get()); | |
1496 | RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), change, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); | |
1497 | ||
1498 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1499 | generator.emitPutByVal(base.get(), property.get(), updatedValue); | |
1500 | ||
1501 | return updatedValue; | |
1502 | } | |
1503 | ||
1504 | // ------------------------------ CommaNode ------------------------------------ | |
1505 | ||
1506 | CommaNode::~CommaNode() | |
1507 | { | |
1508 | NodeReleaser::releaseAllNodes(this); | |
1509 | } | |
1510 | ||
1511 | void CommaNode::releaseNodes(NodeReleaser& releaser) | |
1512 | { | |
1513 | releaser.release(m_expr1); | |
1514 | releaser.release(m_expr2); | |
1515 | } | |
1516 | ||
1517 | RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1518 | { | |
1519 | generator.emitNode(generator.ignoredResult(), m_expr1.get()); | |
1520 | return generator.emitNode(dst, m_expr2.get()); | |
1521 | } | |
1522 | ||
1523 | // ------------------------------ ConstDeclNode ------------------------------------ | |
1524 | ||
1525 | ConstDeclNode::~ConstDeclNode() | |
1526 | { | |
1527 | NodeReleaser::releaseAllNodes(this); | |
1528 | } | |
1529 | ||
1530 | void ConstDeclNode::releaseNodes(NodeReleaser& releaser) | |
1531 | { | |
1532 | releaser.release(m_next); | |
1533 | releaser.release(m_init); | |
1534 | } | |
1535 | ||
1536 | ConstDeclNode::ConstDeclNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* init) | |
1537 | : ExpressionNode(globalData) | |
1538 | , m_ident(ident) | |
1539 | , m_init(init) | |
1540 | { | |
1541 | } | |
1542 | ||
1543 | RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) | |
1544 | { | |
1545 | if (RegisterID* local = generator.constRegisterFor(m_ident)) { | |
1546 | if (!m_init) | |
1547 | return local; | |
1548 | ||
1549 | return generator.emitNode(local, m_init.get()); | |
1550 | } | |
1551 | ||
1552 | // FIXME: While this code should only be hit in eval code, it will potentially | |
1553 | // assign to the wrong base if m_ident exists in an intervening dynamic scope. | |
1554 | RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); | |
1555 | RegisterID* value = m_init ? generator.emitNode(m_init.get()) : generator.emitLoad(0, jsUndefined()); | |
1556 | return generator.emitPutById(base.get(), m_ident, value); | |
1557 | } | |
1558 | ||
1559 | RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
1560 | { | |
1561 | RegisterID* result = 0; | |
1562 | for (ConstDeclNode* n = this; n; n = n->m_next.get()) | |
1563 | result = n->emitCodeSingle(generator); | |
1564 | ||
1565 | return result; | |
1566 | } | |
1567 | ||
1568 | // ------------------------------ ConstStatementNode ----------------------------- | |
1569 | ||
1570 | ConstStatementNode::~ConstStatementNode() | |
1571 | { | |
1572 | NodeReleaser::releaseAllNodes(this); | |
1573 | } | |
1574 | ||
1575 | void ConstStatementNode::releaseNodes(NodeReleaser& releaser) | |
1576 | { | |
1577 | releaser.release(m_next); | |
1578 | } | |
1579 | ||
1580 | RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
1581 | { | |
1582 | return generator.emitNode(m_next.get()); | |
1583 | } | |
1584 | ||
1585 | // ------------------------------ Helper functions for handling Vectors of StatementNode ------------------------------- | |
1586 | ||
1587 | static inline RegisterID* statementListEmitCode(const StatementVector& statements, BytecodeGenerator& generator, RegisterID* dst) | |
1588 | { | |
1589 | StatementVector::const_iterator end = statements.end(); | |
1590 | for (StatementVector::const_iterator it = statements.begin(); it != end; ++it) { | |
1591 | StatementNode* n = it->get(); | |
1592 | if (!n->isLoop()) | |
1593 | generator.emitDebugHook(WillExecuteStatement, n->firstLine(), n->lastLine()); | |
1594 | generator.emitNode(dst, n); | |
1595 | } | |
1596 | return 0; | |
1597 | } | |
1598 | ||
1599 | // ------------------------------ BlockNode ------------------------------------ | |
1600 | ||
1601 | BlockNode::~BlockNode() | |
1602 | { | |
1603 | NodeReleaser::releaseAllNodes(this); | |
1604 | } | |
1605 | ||
1606 | void BlockNode::releaseNodes(NodeReleaser& releaser) | |
1607 | { | |
1608 | size_t size = m_children.size(); | |
1609 | for (size_t i = 0; i < size; ++i) | |
1610 | releaser.release(m_children[i]); | |
1611 | } | |
1612 | ||
1613 | BlockNode::BlockNode(JSGlobalData* globalData, SourceElements* children) | |
1614 | : StatementNode(globalData) | |
1615 | { | |
1616 | if (children) | |
1617 | children->releaseContentsIntoVector(m_children); | |
1618 | } | |
1619 | ||
1620 | RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1621 | { | |
1622 | return statementListEmitCode(m_children, generator, dst); | |
1623 | } | |
1624 | ||
1625 | // ------------------------------ EmptyStatementNode --------------------------- | |
1626 | ||
1627 | RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator&, RegisterID* dst) | |
1628 | { | |
1629 | return dst; | |
1630 | } | |
1631 | ||
1632 | // ------------------------------ DebuggerStatementNode --------------------------- | |
1633 | ||
1634 | RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1635 | { | |
1636 | generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine()); | |
1637 | return dst; | |
1638 | } | |
1639 | ||
1640 | // ------------------------------ ExprStatementNode ---------------------------- | |
1641 | ||
1642 | RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1643 | { | |
1644 | ASSERT(m_expr); | |
1645 | return generator.emitNode(dst, m_expr.get()); | |
1646 | } | |
1647 | ||
1648 | // ------------------------------ VarStatementNode ---------------------------- | |
1649 | ||
1650 | VarStatementNode::~VarStatementNode() | |
1651 | { | |
1652 | NodeReleaser::releaseAllNodes(this); | |
1653 | } | |
1654 | ||
1655 | void VarStatementNode::releaseNodes(NodeReleaser& releaser) | |
1656 | { | |
1657 | releaser.release(m_expr); | |
1658 | } | |
1659 | ||
1660 | RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
1661 | { | |
1662 | ASSERT(m_expr); | |
1663 | return generator.emitNode(m_expr.get()); | |
1664 | } | |
1665 | ||
1666 | // ------------------------------ IfNode --------------------------------------- | |
1667 | ||
1668 | IfNode::~IfNode() | |
1669 | { | |
1670 | NodeReleaser::releaseAllNodes(this); | |
1671 | } | |
1672 | ||
1673 | void IfNode::releaseNodes(NodeReleaser& releaser) | |
1674 | { | |
1675 | releaser.release(m_condition); | |
1676 | releaser.release(m_ifBlock); | |
1677 | } | |
1678 | ||
1679 | RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1680 | { | |
1681 | RefPtr<Label> afterThen = generator.newLabel(); | |
1682 | ||
1683 | RegisterID* cond = generator.emitNode(m_condition.get()); | |
1684 | generator.emitJumpIfFalse(cond, afterThen.get()); | |
1685 | ||
1686 | if (!m_ifBlock->isBlock()) | |
1687 | generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine()); | |
1688 | ||
1689 | generator.emitNode(dst, m_ifBlock.get()); | |
1690 | generator.emitLabel(afterThen.get()); | |
1691 | ||
1692 | // FIXME: This should return the last statement executed so that it can be returned as a Completion. | |
1693 | return 0; | |
1694 | } | |
1695 | ||
1696 | // ------------------------------ IfElseNode --------------------------------------- | |
1697 | ||
1698 | IfElseNode::~IfElseNode() | |
1699 | { | |
1700 | NodeReleaser::releaseAllNodes(this); | |
1701 | } | |
1702 | ||
1703 | void IfElseNode::releaseNodes(NodeReleaser& releaser) | |
1704 | { | |
1705 | releaser.release(m_elseBlock); | |
1706 | IfNode::releaseNodes(releaser); | |
1707 | } | |
1708 | ||
1709 | RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1710 | { | |
1711 | RefPtr<Label> beforeElse = generator.newLabel(); | |
1712 | RefPtr<Label> afterElse = generator.newLabel(); | |
1713 | ||
1714 | RegisterID* cond = generator.emitNode(m_condition.get()); | |
1715 | generator.emitJumpIfFalse(cond, beforeElse.get()); | |
1716 | ||
1717 | if (!m_ifBlock->isBlock()) | |
1718 | generator.emitDebugHook(WillExecuteStatement, m_ifBlock->firstLine(), m_ifBlock->lastLine()); | |
1719 | ||
1720 | generator.emitNode(dst, m_ifBlock.get()); | |
1721 | generator.emitJump(afterElse.get()); | |
1722 | ||
1723 | generator.emitLabel(beforeElse.get()); | |
1724 | ||
1725 | if (!m_elseBlock->isBlock()) | |
1726 | generator.emitDebugHook(WillExecuteStatement, m_elseBlock->firstLine(), m_elseBlock->lastLine()); | |
1727 | ||
1728 | generator.emitNode(dst, m_elseBlock.get()); | |
1729 | ||
1730 | generator.emitLabel(afterElse.get()); | |
1731 | ||
1732 | // FIXME: This should return the last statement executed so that it can be returned as a Completion. | |
1733 | return 0; | |
1734 | } | |
1735 | ||
1736 | // ------------------------------ DoWhileNode ---------------------------------- | |
1737 | ||
1738 | DoWhileNode::~DoWhileNode() | |
1739 | { | |
1740 | NodeReleaser::releaseAllNodes(this); | |
1741 | } | |
1742 | ||
1743 | void DoWhileNode::releaseNodes(NodeReleaser& releaser) | |
1744 | { | |
1745 | releaser.release(m_statement); | |
1746 | releaser.release(m_expr); | |
1747 | } | |
1748 | ||
1749 | RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1750 | { | |
1751 | RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); | |
1752 | ||
1753 | RefPtr<Label> topOfLoop = generator.newLabel(); | |
1754 | generator.emitLabel(topOfLoop.get()); | |
1755 | ||
1756 | generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); | |
1757 | ||
1758 | if (!m_statement->isBlock()) | |
1759 | generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); | |
1760 | ||
1761 | RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get()); | |
1762 | ||
1763 | generator.emitLabel(scope->continueTarget()); | |
1764 | generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); | |
1765 | RegisterID* cond = generator.emitNode(m_expr.get()); | |
1766 | generator.emitJumpIfTrue(cond, topOfLoop.get()); | |
1767 | ||
1768 | generator.emitLabel(scope->breakTarget()); | |
1769 | return result.get(); | |
1770 | } | |
1771 | ||
1772 | // ------------------------------ WhileNode ------------------------------------ | |
1773 | ||
1774 | WhileNode::~WhileNode() | |
1775 | { | |
1776 | NodeReleaser::releaseAllNodes(this); | |
1777 | } | |
1778 | ||
1779 | void WhileNode::releaseNodes(NodeReleaser& releaser) | |
1780 | { | |
1781 | releaser.release(m_expr); | |
1782 | releaser.release(m_statement); | |
1783 | } | |
1784 | ||
1785 | RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1786 | { | |
1787 | RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); | |
1788 | ||
1789 | generator.emitJump(scope->continueTarget()); | |
1790 | ||
1791 | RefPtr<Label> topOfLoop = generator.newLabel(); | |
1792 | generator.emitLabel(topOfLoop.get()); | |
1793 | ||
1794 | if (!m_statement->isBlock()) | |
1795 | generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); | |
1796 | ||
1797 | generator.emitNode(dst, m_statement.get()); | |
1798 | ||
1799 | generator.emitLabel(scope->continueTarget()); | |
1800 | generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); | |
1801 | RegisterID* cond = generator.emitNode(m_expr.get()); | |
1802 | generator.emitJumpIfTrue(cond, topOfLoop.get()); | |
1803 | ||
1804 | generator.emitLabel(scope->breakTarget()); | |
1805 | ||
1806 | // FIXME: This should return the last statement executed so that it can be returned as a Completion | |
1807 | return 0; | |
1808 | } | |
1809 | ||
1810 | // ------------------------------ ForNode -------------------------------------- | |
1811 | ||
1812 | ForNode::~ForNode() | |
1813 | { | |
1814 | NodeReleaser::releaseAllNodes(this); | |
1815 | } | |
1816 | ||
1817 | void ForNode::releaseNodes(NodeReleaser& releaser) | |
1818 | { | |
1819 | releaser.release(m_expr1); | |
1820 | releaser.release(m_expr2); | |
1821 | releaser.release(m_expr3); | |
1822 | releaser.release(m_statement); | |
1823 | } | |
1824 | ||
1825 | RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1826 | { | |
1827 | if (dst == generator.ignoredResult()) | |
1828 | dst = 0; | |
1829 | ||
1830 | RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); | |
1831 | ||
1832 | generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); | |
1833 | ||
1834 | if (m_expr1) | |
1835 | generator.emitNode(generator.ignoredResult(), m_expr1.get()); | |
1836 | ||
1837 | RefPtr<Label> condition = generator.newLabel(); | |
1838 | generator.emitJump(condition.get()); | |
1839 | ||
1840 | RefPtr<Label> topOfLoop = generator.newLabel(); | |
1841 | generator.emitLabel(topOfLoop.get()); | |
1842 | ||
1843 | if (!m_statement->isBlock()) | |
1844 | generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); | |
1845 | RefPtr<RegisterID> result = generator.emitNode(dst, m_statement.get()); | |
1846 | ||
1847 | generator.emitLabel(scope->continueTarget()); | |
1848 | if (m_expr3) | |
1849 | generator.emitNode(generator.ignoredResult(), m_expr3.get()); | |
1850 | ||
1851 | generator.emitLabel(condition.get()); | |
1852 | if (m_expr2) { | |
1853 | RegisterID* cond = generator.emitNode(m_expr2.get()); | |
1854 | generator.emitJumpIfTrue(cond, topOfLoop.get()); | |
1855 | } else | |
1856 | generator.emitJump(topOfLoop.get()); | |
1857 | ||
1858 | generator.emitLabel(scope->breakTarget()); | |
1859 | return result.get(); | |
1860 | } | |
1861 | ||
1862 | // ------------------------------ ForInNode ------------------------------------ | |
1863 | ||
1864 | ForInNode::~ForInNode() | |
1865 | { | |
1866 | NodeReleaser::releaseAllNodes(this); | |
1867 | } | |
1868 | ||
1869 | void ForInNode::releaseNodes(NodeReleaser& releaser) | |
1870 | { | |
1871 | releaser.release(m_init); | |
1872 | releaser.release(m_lexpr); | |
1873 | releaser.release(m_expr); | |
1874 | releaser.release(m_statement); | |
1875 | } | |
1876 | ||
1877 | ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) | |
1878 | : StatementNode(globalData) | |
1879 | , m_init(0L) | |
1880 | , m_lexpr(l) | |
1881 | , m_expr(expr) | |
1882 | , m_statement(statement) | |
1883 | , m_identIsVarDecl(false) | |
1884 | { | |
1885 | } | |
1886 | ||
1887 | ForInNode::ForInNode(JSGlobalData* globalData, const Identifier& ident, ExpressionNode* in, ExpressionNode* expr, StatementNode* statement, int divot, int startOffset, int endOffset) | |
1888 | : StatementNode(globalData) | |
1889 | , m_ident(ident) | |
1890 | , m_lexpr(new ResolveNode(globalData, ident, divot - startOffset)) | |
1891 | , m_expr(expr) | |
1892 | , m_statement(statement) | |
1893 | , m_identIsVarDecl(true) | |
1894 | { | |
1895 | if (in) { | |
1896 | AssignResolveNode* node = new AssignResolveNode(globalData, ident, in, true); | |
1897 | node->setExceptionSourceCode(divot, divot - startOffset, endOffset - divot); | |
1898 | m_init = node; | |
1899 | } | |
1900 | // for( var foo = bar in baz ) | |
1901 | } | |
1902 | ||
1903 | RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1904 | { | |
1905 | RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); | |
1906 | ||
1907 | if (!m_lexpr->isLocation()) | |
1908 | return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference."); | |
1909 | ||
1910 | RefPtr<Label> continueTarget = generator.newLabel(); | |
1911 | ||
1912 | generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); | |
1913 | ||
1914 | if (m_init) | |
1915 | generator.emitNode(generator.ignoredResult(), m_init.get()); | |
1916 | RegisterID* forInBase = generator.emitNode(m_expr.get()); | |
1917 | RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase); | |
1918 | generator.emitJump(scope->continueTarget()); | |
1919 | ||
1920 | RefPtr<Label> loopStart = generator.newLabel(); | |
1921 | generator.emitLabel(loopStart.get()); | |
1922 | ||
1923 | RegisterID* propertyName; | |
1924 | if (m_lexpr->isResolveNode()) { | |
1925 | const Identifier& ident = static_cast<ResolveNode*>(m_lexpr.get())->identifier(); | |
1926 | propertyName = generator.registerFor(ident); | |
1927 | if (!propertyName) { | |
1928 | propertyName = generator.newTemporary(); | |
1929 | RefPtr<RegisterID> protect = propertyName; | |
1930 | RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident); | |
1931 | ||
1932 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
1933 | generator.emitPutById(base, ident, propertyName); | |
1934 | } | |
1935 | } else if (m_lexpr->isDotAccessorNode()) { | |
1936 | DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr.get()); | |
1937 | const Identifier& ident = assignNode->identifier(); | |
1938 | propertyName = generator.newTemporary(); | |
1939 | RefPtr<RegisterID> protect = propertyName; | |
1940 | RegisterID* base = generator.emitNode(assignNode->base()); | |
1941 | ||
1942 | generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); | |
1943 | generator.emitPutById(base, ident, propertyName); | |
1944 | } else { | |
1945 | ASSERT(m_lexpr->isBracketAccessorNode()); | |
1946 | BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr.get()); | |
1947 | propertyName = generator.newTemporary(); | |
1948 | RefPtr<RegisterID> protect = propertyName; | |
1949 | RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); | |
1950 | RegisterID* subscript = generator.emitNode(assignNode->subscript()); | |
1951 | ||
1952 | generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); | |
1953 | generator.emitPutByVal(base.get(), subscript, propertyName); | |
1954 | } | |
1955 | ||
1956 | if (!m_statement->isBlock()) | |
1957 | generator.emitDebugHook(WillExecuteStatement, m_statement->firstLine(), m_statement->lastLine()); | |
1958 | generator.emitNode(dst, m_statement.get()); | |
1959 | ||
1960 | generator.emitLabel(scope->continueTarget()); | |
1961 | generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get()); | |
1962 | generator.emitLabel(scope->breakTarget()); | |
1963 | return dst; | |
1964 | } | |
1965 | ||
1966 | // ------------------------------ ContinueNode --------------------------------- | |
1967 | ||
1968 | // ECMA 12.7 | |
1969 | RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1970 | { | |
1971 | LabelScope* scope = generator.continueTarget(m_ident); | |
1972 | ||
1973 | if (!scope) | |
1974 | return m_ident.isEmpty() | |
1975 | ? emitThrowError(generator, SyntaxError, "Invalid continue statement.") | |
1976 | : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); | |
1977 | ||
1978 | generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth()); | |
1979 | return dst; | |
1980 | } | |
1981 | ||
1982 | // ------------------------------ BreakNode ------------------------------------ | |
1983 | ||
1984 | // ECMA 12.8 | |
1985 | RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
1986 | { | |
1987 | LabelScope* scope = generator.breakTarget(m_ident); | |
1988 | ||
1989 | if (!scope) | |
1990 | return m_ident.isEmpty() | |
1991 | ? emitThrowError(generator, SyntaxError, "Invalid break statement.") | |
1992 | : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); | |
1993 | ||
1994 | generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth()); | |
1995 | return dst; | |
1996 | } | |
1997 | ||
1998 | // ------------------------------ ReturnNode ----------------------------------- | |
1999 | ||
2000 | ReturnNode::~ReturnNode() | |
2001 | { | |
2002 | NodeReleaser::releaseAllNodes(this); | |
2003 | } | |
2004 | ||
2005 | void ReturnNode::releaseNodes(NodeReleaser& releaser) | |
2006 | { | |
2007 | releaser.release(m_value); | |
2008 | } | |
2009 | ||
2010 | RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2011 | { | |
2012 | if (generator.codeType() != FunctionCode) | |
2013 | return emitThrowError(generator, SyntaxError, "Invalid return statement."); | |
2014 | ||
2015 | if (dst == generator.ignoredResult()) | |
2016 | dst = 0; | |
2017 | RegisterID* r0 = m_value ? generator.emitNode(dst, m_value.get()) : generator.emitLoad(dst, jsUndefined()); | |
2018 | RefPtr<RegisterID> returnRegister; | |
2019 | if (generator.scopeDepth()) { | |
2020 | RefPtr<Label> l0 = generator.newLabel(); | |
2021 | if (generator.hasFinaliser() && !r0->isTemporary()) { | |
2022 | returnRegister = generator.emitMove(generator.newTemporary(), r0); | |
2023 | r0 = returnRegister.get(); | |
2024 | } | |
2025 | generator.emitJumpScopes(l0.get(), 0); | |
2026 | generator.emitLabel(l0.get()); | |
2027 | } | |
2028 | generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); | |
2029 | return generator.emitReturn(r0); | |
2030 | } | |
2031 | ||
2032 | // ------------------------------ WithNode ------------------------------------- | |
2033 | ||
2034 | WithNode::~WithNode() | |
2035 | { | |
2036 | NodeReleaser::releaseAllNodes(this); | |
2037 | } | |
2038 | ||
2039 | void WithNode::releaseNodes(NodeReleaser& releaser) | |
2040 | { | |
2041 | releaser.release(m_expr); | |
2042 | releaser.release(m_statement); | |
2043 | } | |
2044 | ||
2045 | RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2046 | { | |
2047 | RefPtr<RegisterID> scope = generator.newTemporary(); | |
2048 | generator.emitNode(scope.get(), m_expr.get()); // scope must be protected until popped | |
2049 | generator.emitExpressionInfo(m_divot, m_expressionLength, 0); | |
2050 | generator.emitPushScope(scope.get()); | |
2051 | RegisterID* result = generator.emitNode(dst, m_statement.get()); | |
2052 | generator.emitPopScope(); | |
2053 | return result; | |
2054 | } | |
2055 | ||
2056 | // ------------------------------ CaseClauseNode -------------------------------- | |
2057 | ||
2058 | CaseClauseNode::~CaseClauseNode() | |
2059 | { | |
2060 | NodeReleaser::releaseAllNodes(this); | |
2061 | } | |
2062 | ||
2063 | void CaseClauseNode::releaseNodes(NodeReleaser& releaser) | |
2064 | { | |
2065 | releaser.release(m_expr); | |
2066 | } | |
2067 | ||
2068 | // ------------------------------ ClauseListNode -------------------------------- | |
2069 | ||
2070 | ClauseListNode::~ClauseListNode() | |
2071 | { | |
2072 | NodeReleaser::releaseAllNodes(this); | |
2073 | } | |
2074 | ||
2075 | void ClauseListNode::releaseNodes(NodeReleaser& releaser) | |
2076 | { | |
2077 | releaser.release(m_clause); | |
2078 | releaser.release(m_next); | |
2079 | } | |
2080 | ||
2081 | // ------------------------------ CaseBlockNode -------------------------------- | |
2082 | ||
2083 | CaseBlockNode::~CaseBlockNode() | |
2084 | { | |
2085 | NodeReleaser::releaseAllNodes(this); | |
2086 | } | |
2087 | ||
2088 | void CaseBlockNode::releaseNodes(NodeReleaser& releaser) | |
2089 | { | |
2090 | releaser.release(m_list1); | |
2091 | releaser.release(m_defaultClause); | |
2092 | releaser.release(m_list2); | |
2093 | } | |
2094 | ||
2095 | enum SwitchKind { | |
2096 | SwitchUnset = 0, | |
2097 | SwitchNumber = 1, | |
2098 | SwitchString = 2, | |
2099 | SwitchNeither = 3 | |
2100 | }; | |
2101 | ||
2102 | static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num) | |
2103 | { | |
2104 | for (; list; list = list->getNext()) { | |
2105 | ExpressionNode* clauseExpression = list->getClause()->expr(); | |
2106 | literalVector.append(clauseExpression); | |
2107 | if (clauseExpression->isNumber()) { | |
2108 | double value = static_cast<NumberNode*>(clauseExpression)->value(); | |
2109 | JSValuePtr jsValue = JSValuePtr::makeInt32Fast(static_cast<int32_t>(value)); | |
2110 | if ((typeForTable & ~SwitchNumber) || !jsValue || (jsValue.getInt32Fast() != value)) { | |
2111 | typeForTable = SwitchNeither; | |
2112 | break; | |
2113 | } | |
2114 | int32_t intVal = static_cast<int32_t>(value); | |
2115 | ASSERT(intVal == value); | |
2116 | if (intVal < min_num) | |
2117 | min_num = intVal; | |
2118 | if (intVal > max_num) | |
2119 | max_num = intVal; | |
2120 | typeForTable = SwitchNumber; | |
2121 | continue; | |
2122 | } | |
2123 | if (clauseExpression->isString()) { | |
2124 | if (typeForTable & ~SwitchString) { | |
2125 | typeForTable = SwitchNeither; | |
2126 | break; | |
2127 | } | |
2128 | const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring(); | |
2129 | if (singleCharacterSwitch &= value.size() == 1) { | |
2130 | int32_t intVal = value.rep()->data()[0]; | |
2131 | if (intVal < min_num) | |
2132 | min_num = intVal; | |
2133 | if (intVal > max_num) | |
2134 | max_num = intVal; | |
2135 | } | |
2136 | typeForTable = SwitchString; | |
2137 | continue; | |
2138 | } | |
2139 | typeForTable = SwitchNeither; | |
2140 | break; | |
2141 | } | |
2142 | } | |
2143 | ||
2144 | SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num) | |
2145 | { | |
2146 | SwitchKind typeForTable = SwitchUnset; | |
2147 | bool singleCharacterSwitch = true; | |
2148 | ||
2149 | processClauseList(m_list1.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); | |
2150 | processClauseList(m_list2.get(), literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); | |
2151 | ||
2152 | if (typeForTable == SwitchUnset || typeForTable == SwitchNeither) | |
2153 | return SwitchInfo::SwitchNone; | |
2154 | ||
2155 | if (typeForTable == SwitchNumber) { | |
2156 | int32_t range = max_num - min_num; | |
2157 | if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) | |
2158 | return SwitchInfo::SwitchImmediate; | |
2159 | return SwitchInfo::SwitchNone; | |
2160 | } | |
2161 | ||
2162 | ASSERT(typeForTable == SwitchString); | |
2163 | ||
2164 | if (singleCharacterSwitch) { | |
2165 | int32_t range = max_num - min_num; | |
2166 | if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) | |
2167 | return SwitchInfo::SwitchCharacter; | |
2168 | } | |
2169 | ||
2170 | return SwitchInfo::SwitchString; | |
2171 | } | |
2172 | ||
2173 | RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst) | |
2174 | { | |
2175 | RefPtr<Label> defaultLabel; | |
2176 | Vector<RefPtr<Label>, 8> labelVector; | |
2177 | Vector<ExpressionNode*, 8> literalVector; | |
2178 | int32_t min_num = std::numeric_limits<int32_t>::max(); | |
2179 | int32_t max_num = std::numeric_limits<int32_t>::min(); | |
2180 | SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num); | |
2181 | ||
2182 | if (switchType != SwitchInfo::SwitchNone) { | |
2183 | // Prepare the various labels | |
2184 | for (uint32_t i = 0; i < literalVector.size(); i++) | |
2185 | labelVector.append(generator.newLabel()); | |
2186 | defaultLabel = generator.newLabel(); | |
2187 | generator.beginSwitch(switchExpression, switchType); | |
2188 | } else { | |
2189 | // Setup jumps | |
2190 | for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) { | |
2191 | RefPtr<RegisterID> clauseVal = generator.newTemporary(); | |
2192 | generator.emitNode(clauseVal.get(), list->getClause()->expr()); | |
2193 | generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); | |
2194 | labelVector.append(generator.newLabel()); | |
2195 | generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); | |
2196 | } | |
2197 | ||
2198 | for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) { | |
2199 | RefPtr<RegisterID> clauseVal = generator.newTemporary(); | |
2200 | generator.emitNode(clauseVal.get(), list->getClause()->expr()); | |
2201 | generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); | |
2202 | labelVector.append(generator.newLabel()); | |
2203 | generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); | |
2204 | } | |
2205 | defaultLabel = generator.newLabel(); | |
2206 | generator.emitJump(defaultLabel.get()); | |
2207 | } | |
2208 | ||
2209 | RegisterID* result = 0; | |
2210 | ||
2211 | size_t i = 0; | |
2212 | for (ClauseListNode* list = m_list1.get(); list; list = list->getNext()) { | |
2213 | generator.emitLabel(labelVector[i++].get()); | |
2214 | result = statementListEmitCode(list->getClause()->children(), generator, dst); | |
2215 | } | |
2216 | ||
2217 | if (m_defaultClause) { | |
2218 | generator.emitLabel(defaultLabel.get()); | |
2219 | result = statementListEmitCode(m_defaultClause->children(), generator, dst); | |
2220 | } | |
2221 | ||
2222 | for (ClauseListNode* list = m_list2.get(); list; list = list->getNext()) { | |
2223 | generator.emitLabel(labelVector[i++].get()); | |
2224 | result = statementListEmitCode(list->getClause()->children(), generator, dst); | |
2225 | } | |
2226 | if (!m_defaultClause) | |
2227 | generator.emitLabel(defaultLabel.get()); | |
2228 | ||
2229 | ASSERT(i == labelVector.size()); | |
2230 | if (switchType != SwitchInfo::SwitchNone) { | |
2231 | ASSERT(labelVector.size() == literalVector.size()); | |
2232 | generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num); | |
2233 | } | |
2234 | return result; | |
2235 | } | |
2236 | ||
2237 | // ------------------------------ SwitchNode ----------------------------------- | |
2238 | ||
2239 | SwitchNode::~SwitchNode() | |
2240 | { | |
2241 | NodeReleaser::releaseAllNodes(this); | |
2242 | } | |
2243 | ||
2244 | void SwitchNode::releaseNodes(NodeReleaser& releaser) | |
2245 | { | |
2246 | releaser.release(m_expr); | |
2247 | releaser.release(m_block); | |
2248 | } | |
2249 | ||
2250 | RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2251 | { | |
2252 | RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); | |
2253 | ||
2254 | RefPtr<RegisterID> r0 = generator.emitNode(m_expr.get()); | |
2255 | RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst); | |
2256 | ||
2257 | generator.emitLabel(scope->breakTarget()); | |
2258 | return r1; | |
2259 | } | |
2260 | ||
2261 | // ------------------------------ LabelNode ------------------------------------ | |
2262 | ||
2263 | LabelNode::~LabelNode() | |
2264 | { | |
2265 | NodeReleaser::releaseAllNodes(this); | |
2266 | } | |
2267 | ||
2268 | void LabelNode::releaseNodes(NodeReleaser& releaser) | |
2269 | { | |
2270 | releaser.release(m_statement); | |
2271 | } | |
2272 | ||
2273 | RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2274 | { | |
2275 | if (generator.breakTarget(m_name)) | |
2276 | return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); | |
2277 | ||
2278 | RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); | |
2279 | RegisterID* r0 = generator.emitNode(dst, m_statement.get()); | |
2280 | ||
2281 | generator.emitLabel(scope->breakTarget()); | |
2282 | return r0; | |
2283 | } | |
2284 | ||
2285 | // ------------------------------ ThrowNode ------------------------------------ | |
2286 | ||
2287 | ThrowNode::~ThrowNode() | |
2288 | { | |
2289 | NodeReleaser::releaseAllNodes(this); | |
2290 | } | |
2291 | ||
2292 | void ThrowNode::releaseNodes(NodeReleaser& releaser) | |
2293 | { | |
2294 | releaser.release(m_expr); | |
2295 | } | |
2296 | ||
2297 | RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2298 | { | |
2299 | if (dst == generator.ignoredResult()) | |
2300 | dst = 0; | |
2301 | RefPtr<RegisterID> expr = generator.emitNode(dst, m_expr.get()); | |
2302 | generator.emitExpressionInfo(divot(), startOffset(), endOffset()); | |
2303 | generator.emitThrow(expr.get()); | |
2304 | return dst; | |
2305 | } | |
2306 | ||
2307 | // ------------------------------ TryNode -------------------------------------- | |
2308 | ||
2309 | TryNode::~TryNode() | |
2310 | { | |
2311 | NodeReleaser::releaseAllNodes(this); | |
2312 | } | |
2313 | ||
2314 | void TryNode::releaseNodes(NodeReleaser& releaser) | |
2315 | { | |
2316 | releaser.release(m_tryBlock); | |
2317 | releaser.release(m_catchBlock); | |
2318 | releaser.release(m_finallyBlock); | |
2319 | } | |
2320 | ||
2321 | RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2322 | { | |
2323 | RefPtr<Label> tryStartLabel = generator.newLabel(); | |
2324 | RefPtr<Label> tryEndLabel = generator.newLabel(); | |
2325 | RefPtr<Label> finallyStart; | |
2326 | RefPtr<RegisterID> finallyReturnAddr; | |
2327 | if (m_finallyBlock) { | |
2328 | finallyStart = generator.newLabel(); | |
2329 | finallyReturnAddr = generator.newTemporary(); | |
2330 | generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); | |
2331 | } | |
2332 | generator.emitLabel(tryStartLabel.get()); | |
2333 | generator.emitNode(dst, m_tryBlock.get()); | |
2334 | generator.emitLabel(tryEndLabel.get()); | |
2335 | ||
2336 | if (m_catchBlock) { | |
2337 | RefPtr<Label> handlerEndLabel = generator.newLabel(); | |
2338 | generator.emitJump(handlerEndLabel.get()); | |
2339 | RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), tryEndLabel.get()); | |
2340 | if (m_catchHasEval) { | |
2341 | RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary()); | |
2342 | generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get()); | |
2343 | generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get()); | |
2344 | generator.emitPushScope(exceptionRegister.get()); | |
2345 | } else | |
2346 | generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); | |
2347 | generator.emitNode(dst, m_catchBlock.get()); | |
2348 | generator.emitPopScope(); | |
2349 | generator.emitLabel(handlerEndLabel.get()); | |
2350 | } | |
2351 | ||
2352 | if (m_finallyBlock) { | |
2353 | generator.popFinallyContext(); | |
2354 | // there may be important registers live at the time we jump | |
2355 | // to a finally block (such as for a return or throw) so we | |
2356 | // ref the highest register ever used as a conservative | |
2357 | // approach to not clobbering anything important | |
2358 | RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister(); | |
2359 | RefPtr<Label> finallyEndLabel = generator.newLabel(); | |
2360 | generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); | |
2361 | // Use a label to record the subtle fact that sret will return to the | |
2362 | // next instruction. sret is the only way to jump without an explicit label. | |
2363 | generator.emitLabel(generator.newLabel().get()); | |
2364 | generator.emitJump(finallyEndLabel.get()); | |
2365 | ||
2366 | // Finally block for exception path | |
2367 | RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), generator.emitLabel(generator.newLabel().get()).get()); | |
2368 | generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); | |
2369 | // Use a label to record the subtle fact that sret will return to the | |
2370 | // next instruction. sret is the only way to jump without an explicit label. | |
2371 | generator.emitLabel(generator.newLabel().get()); | |
2372 | generator.emitThrow(tempExceptionRegister.get()); | |
2373 | ||
2374 | // emit the finally block itself | |
2375 | generator.emitLabel(finallyStart.get()); | |
2376 | generator.emitNode(dst, m_finallyBlock.get()); | |
2377 | generator.emitSubroutineReturn(finallyReturnAddr.get()); | |
2378 | ||
2379 | generator.emitLabel(finallyEndLabel.get()); | |
2380 | } | |
2381 | ||
2382 | return dst; | |
2383 | } | |
2384 | ||
2385 | // ------------------------------ ParameterNode ----------------------------- | |
2386 | ||
2387 | ParameterNode::~ParameterNode() | |
2388 | { | |
2389 | NodeReleaser::releaseAllNodes(this); | |
2390 | } | |
2391 | ||
2392 | void ParameterNode::releaseNodes(NodeReleaser& releaser) | |
2393 | { | |
2394 | releaser.release(m_next); | |
2395 | } | |
2396 | ||
2397 | // -----------------------------ScopeNodeData --------------------------- | |
2398 | ||
2399 | ScopeNodeData::ScopeNodeData(SourceElements* children, VarStack* varStack, FunctionStack* funcStack, int numConstants) | |
2400 | : m_numConstants(numConstants) | |
2401 | { | |
2402 | if (varStack) | |
2403 | m_varStack = *varStack; | |
2404 | if (funcStack) | |
2405 | m_functionStack = *funcStack; | |
2406 | if (children) | |
2407 | children->releaseContentsIntoVector(m_children); | |
2408 | } | |
2409 | ||
2410 | void ScopeNodeData::mark() | |
2411 | { | |
2412 | FunctionStack::iterator end = m_functionStack.end(); | |
2413 | for (FunctionStack::iterator ptr = m_functionStack.begin(); ptr != end; ++ptr) { | |
2414 | FunctionBodyNode* body = (*ptr)->body(); | |
2415 | if (!body->isGenerated()) | |
2416 | continue; | |
2417 | body->generatedBytecode().mark(); | |
2418 | } | |
2419 | } | |
2420 | ||
2421 | // ------------------------------ ScopeNode ----------------------------- | |
2422 | ||
2423 | ScopeNode::ScopeNode(JSGlobalData* globalData) | |
2424 | : StatementNode(globalData) | |
2425 | , m_features(NoFeatures) | |
2426 | { | |
2427 | #if ENABLE(OPCODE_SAMPLING) | |
2428 | globalData->interpreter->sampler()->notifyOfScope(this); | |
2429 | #endif | |
2430 | } | |
2431 | ||
2432 | ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants) | |
2433 | : StatementNode(globalData) | |
2434 | , m_data(new ScopeNodeData(children, varStack, funcStack, numConstants)) | |
2435 | , m_features(features) | |
2436 | , m_source(source) | |
2437 | { | |
2438 | #if ENABLE(OPCODE_SAMPLING) | |
2439 | globalData->interpreter->sampler()->notifyOfScope(this); | |
2440 | #endif | |
2441 | } | |
2442 | ||
2443 | ScopeNode::~ScopeNode() | |
2444 | { | |
2445 | NodeReleaser::releaseAllNodes(this); | |
2446 | } | |
2447 | ||
2448 | void ScopeNode::releaseNodes(NodeReleaser& releaser) | |
2449 | { | |
2450 | if (!m_data) | |
2451 | return; | |
2452 | size_t size = m_data->m_children.size(); | |
2453 | for (size_t i = 0; i < size; ++i) | |
2454 | releaser.release(m_data->m_children[i]); | |
2455 | } | |
2456 | ||
2457 | // ------------------------------ ProgramNode ----------------------------- | |
2458 | ||
2459 | ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) | |
2460 | : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) | |
2461 | { | |
2462 | } | |
2463 | ||
2464 | ProgramNode* ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) | |
2465 | { | |
2466 | return new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants); | |
2467 | } | |
2468 | ||
2469 | RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
2470 | { | |
2471 | generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); | |
2472 | ||
2473 | RefPtr<RegisterID> dstRegister = generator.newTemporary(); | |
2474 | generator.emitLoad(dstRegister.get(), jsUndefined()); | |
2475 | statementListEmitCode(children(), generator, dstRegister.get()); | |
2476 | ||
2477 | generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); | |
2478 | generator.emitEnd(dstRegister.get()); | |
2479 | return 0; | |
2480 | } | |
2481 | ||
2482 | void ProgramNode::generateBytecode(ScopeChainNode* scopeChainNode) | |
2483 | { | |
2484 | ScopeChain scopeChain(scopeChainNode); | |
2485 | JSGlobalObject* globalObject = scopeChain.globalObject(); | |
2486 | ||
2487 | m_code.set(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider())); | |
2488 | ||
2489 | BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_code.get()); | |
2490 | generator.generate(); | |
2491 | ||
2492 | destroyData(); | |
2493 | } | |
2494 | ||
2495 | // ------------------------------ EvalNode ----------------------------- | |
2496 | ||
2497 | EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) | |
2498 | : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants) | |
2499 | { | |
2500 | } | |
2501 | ||
2502 | EvalNode* EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) | |
2503 | { | |
2504 | return new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants); | |
2505 | } | |
2506 | ||
2507 | RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
2508 | { | |
2509 | generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); | |
2510 | ||
2511 | RefPtr<RegisterID> dstRegister = generator.newTemporary(); | |
2512 | generator.emitLoad(dstRegister.get(), jsUndefined()); | |
2513 | statementListEmitCode(children(), generator, dstRegister.get()); | |
2514 | ||
2515 | generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); | |
2516 | generator.emitEnd(dstRegister.get()); | |
2517 | return 0; | |
2518 | } | |
2519 | ||
2520 | void EvalNode::generateBytecode(ScopeChainNode* scopeChainNode) | |
2521 | { | |
2522 | ScopeChain scopeChain(scopeChainNode); | |
2523 | JSGlobalObject* globalObject = scopeChain.globalObject(); | |
2524 | ||
2525 | m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); | |
2526 | ||
2527 | BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); | |
2528 | generator.generate(); | |
2529 | ||
2530 | // Eval code needs to hang on to its declaration stacks to keep declaration info alive until Interpreter::execute time, | |
2531 | // so the entire ScopeNodeData cannot be destoyed. | |
2532 | children().clear(); | |
2533 | } | |
2534 | ||
2535 | EvalCodeBlock& EvalNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom) | |
2536 | { | |
2537 | ASSERT(!m_code); | |
2538 | ||
2539 | ScopeChain scopeChain(scopeChainNode); | |
2540 | JSGlobalObject* globalObject = scopeChain.globalObject(); | |
2541 | ||
2542 | m_code.set(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); | |
2543 | ||
2544 | BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); | |
2545 | generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom); | |
2546 | generator.generate(); | |
2547 | ||
2548 | return *m_code; | |
2549 | } | |
2550 | ||
2551 | void EvalNode::mark() | |
2552 | { | |
2553 | // We don't need to mark our own CodeBlock as the JSGlobalObject takes care of that | |
2554 | data()->mark(); | |
2555 | } | |
2556 | ||
2557 | // ------------------------------ FunctionBodyNode ----------------------------- | |
2558 | ||
2559 | FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData) | |
2560 | : ScopeNode(globalData) | |
2561 | , m_parameters(0) | |
2562 | , m_parameterCount(0) | |
2563 | , m_refCount(0) | |
2564 | { | |
2565 | } | |
2566 | ||
2567 | FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) | |
2568 | : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants) | |
2569 | , m_parameters(0) | |
2570 | , m_parameterCount(0) | |
2571 | , m_refCount(0) | |
2572 | { | |
2573 | } | |
2574 | ||
2575 | FunctionBodyNode::~FunctionBodyNode() | |
2576 | { | |
2577 | ASSERT(!m_refCount); | |
2578 | for (size_t i = 0; i < m_parameterCount; ++i) | |
2579 | m_parameters[i].~Identifier(); | |
2580 | fastFree(m_parameters); | |
2581 | } | |
2582 | ||
2583 | void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter) | |
2584 | { | |
2585 | Vector<Identifier> parameters; | |
2586 | for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam()) | |
2587 | parameters.append(parameter->ident()); | |
2588 | size_t count = parameters.size(); | |
2589 | ||
2590 | setSource(source); | |
2591 | finishParsing(parameters.releaseBuffer(), count); | |
2592 | } | |
2593 | ||
2594 | void FunctionBodyNode::finishParsing(Identifier* parameters, size_t parameterCount) | |
2595 | { | |
2596 | ASSERT(!source().isNull()); | |
2597 | m_parameters = parameters; | |
2598 | m_parameterCount = parameterCount; | |
2599 | } | |
2600 | ||
2601 | void FunctionBodyNode::mark() | |
2602 | { | |
2603 | if (m_code) | |
2604 | m_code->mark(); | |
2605 | } | |
2606 | ||
2607 | FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData) | |
2608 | { | |
2609 | return new FunctionBodyNode(globalData); | |
2610 | } | |
2611 | ||
2612 | FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants) | |
2613 | { | |
2614 | return new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants); | |
2615 | } | |
2616 | ||
2617 | void FunctionBodyNode::generateBytecode(ScopeChainNode* scopeChainNode) | |
2618 | { | |
2619 | // This branch is only necessary since you can still create a non-stub FunctionBodyNode by | |
2620 | // calling Parser::parse<FunctionBodyNode>(). | |
2621 | if (!data()) | |
2622 | scopeChainNode->globalData->parser->reparseInPlace(scopeChainNode->globalData, this); | |
2623 | ASSERT(data()); | |
2624 | ||
2625 | ScopeChain scopeChain(scopeChainNode); | |
2626 | JSGlobalObject* globalObject = scopeChain.globalObject(); | |
2627 | ||
2628 | m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset())); | |
2629 | ||
2630 | BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); | |
2631 | generator.generate(); | |
2632 | ||
2633 | destroyData(); | |
2634 | } | |
2635 | ||
2636 | CodeBlock& FunctionBodyNode::bytecodeForExceptionInfoReparse(ScopeChainNode* scopeChainNode, CodeBlock* codeBlockBeingRegeneratedFrom) | |
2637 | { | |
2638 | ASSERT(!m_code); | |
2639 | ||
2640 | ScopeChain scopeChain(scopeChainNode); | |
2641 | JSGlobalObject* globalObject = scopeChain.globalObject(); | |
2642 | ||
2643 | m_code.set(new CodeBlock(this, FunctionCode, source().provider(), source().startOffset())); | |
2644 | ||
2645 | BytecodeGenerator generator(this, globalObject->debugger(), scopeChain, &m_code->symbolTable(), m_code.get()); | |
2646 | generator.setRegeneratingForExceptionInfo(codeBlockBeingRegeneratedFrom); | |
2647 | generator.generate(); | |
2648 | ||
2649 | return *m_code; | |
2650 | } | |
2651 | ||
2652 | RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) | |
2653 | { | |
2654 | generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); | |
2655 | statementListEmitCode(children(), generator, generator.ignoredResult()); | |
2656 | if (children().size() && children().last()->isBlock()) { | |
2657 | BlockNode* blockNode = static_cast<BlockNode*>(children().last().get()); | |
2658 | if (blockNode->children().size() && blockNode->children().last()->isReturnNode()) | |
2659 | return 0; | |
2660 | } | |
2661 | ||
2662 | RegisterID* r0 = generator.emitLoad(0, jsUndefined()); | |
2663 | generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); | |
2664 | generator.emitReturn(r0); | |
2665 | return 0; | |
2666 | } | |
2667 | ||
2668 | UString FunctionBodyNode::paramString() const | |
2669 | { | |
2670 | UString s(""); | |
2671 | for (size_t pos = 0; pos < m_parameterCount; ++pos) { | |
2672 | if (!s.isEmpty()) | |
2673 | s += ", "; | |
2674 | s += parameters()[pos].ustring(); | |
2675 | } | |
2676 | ||
2677 | return s; | |
2678 | } | |
2679 | ||
2680 | Identifier* FunctionBodyNode::copyParameters() | |
2681 | { | |
2682 | Identifier* parameters = static_cast<Identifier*>(fastMalloc(m_parameterCount * sizeof(Identifier))); | |
2683 | VectorCopier<false, Identifier>::uninitializedCopy(m_parameters, m_parameters + m_parameterCount, parameters); | |
2684 | return parameters; | |
2685 | } | |
2686 | ||
2687 | // ------------------------------ FuncDeclNode --------------------------------- | |
2688 | ||
2689 | FuncDeclNode::~FuncDeclNode() | |
2690 | { | |
2691 | NodeReleaser::releaseAllNodes(this); | |
2692 | } | |
2693 | ||
2694 | void FuncDeclNode::releaseNodes(NodeReleaser& releaser) | |
2695 | { | |
2696 | releaser.release(m_parameter); | |
2697 | releaser.release(m_body); | |
2698 | } | |
2699 | ||
2700 | JSFunction* FuncDeclNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain) | |
2701 | { | |
2702 | return new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain); | |
2703 | } | |
2704 | ||
2705 | RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2706 | { | |
2707 | if (dst == generator.ignoredResult()) | |
2708 | dst = 0; | |
2709 | return dst; | |
2710 | } | |
2711 | ||
2712 | // ------------------------------ FuncExprNode --------------------------------- | |
2713 | ||
2714 | FuncExprNode::~FuncExprNode() | |
2715 | { | |
2716 | NodeReleaser::releaseAllNodes(this); | |
2717 | } | |
2718 | ||
2719 | void FuncExprNode::releaseNodes(NodeReleaser& releaser) | |
2720 | { | |
2721 | releaser.release(m_parameter); | |
2722 | releaser.release(m_body); | |
2723 | } | |
2724 | ||
2725 | RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) | |
2726 | { | |
2727 | return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); | |
2728 | } | |
2729 | ||
2730 | JSFunction* FuncExprNode::makeFunction(ExecState* exec, ScopeChainNode* scopeChain) | |
2731 | { | |
2732 | JSFunction* func = new (exec) JSFunction(exec, m_ident, m_body.get(), scopeChain); | |
2733 | ||
2734 | /* | |
2735 | The Identifier in a FunctionExpression can be referenced from inside | |
2736 | the FunctionExpression's FunctionBody to allow the function to call | |
2737 | itself recursively. However, unlike in a FunctionDeclaration, the | |
2738 | Identifier in a FunctionExpression cannot be referenced from and | |
2739 | does not affect the scope enclosing the FunctionExpression. | |
2740 | */ | |
2741 | ||
2742 | if (!m_ident.isNull()) { | |
2743 | JSStaticScopeObject* functionScopeObject = new (exec) JSStaticScopeObject(exec, m_ident, func, ReadOnly | DontDelete); | |
2744 | func->scope().push(functionScopeObject); | |
2745 | } | |
2746 | ||
2747 | return func; | |
2748 | } | |
2749 | ||
2750 | } // namespace JSC |