blob: 3e6d856ce43cc60a9f587791572840e8a4c7b15c [file] [log] [blame]
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "ast.h"
ager@chromium.org3811b432009-10-28 14:53:37 +000031#include "parser.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032#include "scopes.h"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000033#include "string-stream.h"
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000034#include "type-info.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
kasperl@chromium.org71affb52009-05-26 05:44:31 +000036namespace v8 {
37namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000039AstSentinels::AstSentinels()
rossberg@chromium.org717967f2011-07-20 13:44:42 +000040 : this_proxy_(Isolate::Current(), true),
41 identifier_proxy_(Isolate::Current(), false),
42 valid_left_hand_side_sentinel_(Isolate::Current()),
43 this_property_(Isolate::Current(), &this_proxy_, NULL, 0),
44 call_sentinel_(Isolate::Current(), NULL, NULL, 0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000045}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
47
48// ----------------------------------------------------------------------------
49// All the Accept member functions for each syntax tree node type.
50
kasperl@chromium.orga5551262010-12-07 12:49:48 +000051void Slot::Accept(AstVisitor* v) { v->VisitSlot(this); }
52
lrn@chromium.org25156de2010-04-06 13:10:27 +000053#define DECL_ACCEPT(type) \
54 void type::Accept(AstVisitor* v) { v->Visit##type(this); }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000055AST_NODE_LIST(DECL_ACCEPT)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000056#undef DECL_ACCEPT
57
58
59// ----------------------------------------------------------------------------
60// Implementation of other node functionality.
61
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000062Assignment* ExpressionStatement::StatementAsSimpleAssignment() {
63 return (expression()->AsAssignment() != NULL &&
64 !expression()->AsAssignment()->is_compound())
65 ? expression()->AsAssignment()
66 : NULL;
67}
68
69
70CountOperation* ExpressionStatement::StatementAsCountOperation() {
71 return expression()->AsCountOperation();
72}
73
74
rossberg@chromium.org717967f2011-07-20 13:44:42 +000075VariableProxy::VariableProxy(Isolate* isolate, Variable* var)
76 : Expression(isolate),
77 name_(var->name()),
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000078 var_(NULL), // Will be set by the call to BindTo.
79 is_this_(var->is_this()),
80 inside_with_(false),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000081 is_trivial_(false),
82 position_(RelocInfo::kNoPosition) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000083 BindTo(var);
84}
85
86
rossberg@chromium.org717967f2011-07-20 13:44:42 +000087VariableProxy::VariableProxy(Isolate* isolate,
88 Handle<String> name,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000089 bool is_this,
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000090 bool inside_with,
91 int position)
rossberg@chromium.org717967f2011-07-20 13:44:42 +000092 : Expression(isolate),
93 name_(name),
94 var_(NULL),
95 is_this_(is_this),
96 inside_with_(inside_with),
97 is_trivial_(false),
98 position_(position) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000099 // Names must be canonicalized for fast equality checks.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000100 ASSERT(name->IsSymbol());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000101}
102
103
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000104VariableProxy::VariableProxy(Isolate* isolate, bool is_this)
105 : Expression(isolate),
106 var_(NULL),
107 is_this_(is_this),
108 inside_with_(false),
109 is_trivial_(false) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000110}
111
112
113void VariableProxy::BindTo(Variable* var) {
114 ASSERT(var_ == NULL); // must be bound only once
115 ASSERT(var != NULL); // must bind
116 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
117 // Ideally CONST-ness should match. However, this is very hard to achieve
118 // because we don't know the exact semantics of conflicting (const and
119 // non-const) multiple variable declarations, const vars introduced via
120 // eval() etc. Const-ness and variable declarations are a complete mess
121 // in JS. Sigh...
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122 var_ = var;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000123 var->set_is_used(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124}
125
126
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000127Assignment::Assignment(Isolate* isolate,
128 Token::Value op,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000129 Expression* target,
130 Expression* value,
131 int pos)
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000132 : Expression(isolate),
133 op_(op),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000134 target_(target),
135 value_(value),
136 pos_(pos),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000137 binary_operation_(NULL),
138 compound_load_id_(kNoNumber),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000139 assignment_id_(GetNextId(isolate)),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000140 block_start_(false),
141 block_end_(false),
142 is_monomorphic_(false),
143 receiver_types_(NULL) {
144 ASSERT(Token::IsAssignmentOp(op));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000145 if (is_compound()) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000146 binary_operation_ =
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000147 new(isolate->zone()) BinaryOperation(isolate,
148 binary_op(),
149 target,
150 value,
151 pos + 1);
152 compound_load_id_ = GetNextId(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000153 }
154}
155
156
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157Token::Value Assignment::binary_op() const {
158 switch (op_) {
159 case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
160 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
161 case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
162 case Token::ASSIGN_SHL: return Token::SHL;
163 case Token::ASSIGN_SAR: return Token::SAR;
164 case Token::ASSIGN_SHR: return Token::SHR;
165 case Token::ASSIGN_ADD: return Token::ADD;
166 case Token::ASSIGN_SUB: return Token::SUB;
167 case Token::ASSIGN_MUL: return Token::MUL;
168 case Token::ASSIGN_DIV: return Token::DIV;
169 case Token::ASSIGN_MOD: return Token::MOD;
170 default: UNREACHABLE();
171 }
172 return Token::ILLEGAL;
173}
174
175
176bool FunctionLiteral::AllowsLazyCompilation() {
177 return scope()->AllowsLazyCompilation();
178}
179
180
181ObjectLiteral::Property::Property(Literal* key, Expression* value) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000182 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183 key_ = key;
184 value_ = value;
185 Object* k = *key->handle();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000186 if (k->IsSymbol() && HEAP->Proto_symbol()->Equals(String::cast(k))) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000187 kind_ = PROTOTYPE;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000188 } else if (value_->AsMaterializedLiteral() != NULL) {
189 kind_ = MATERIALIZED_LITERAL;
190 } else if (value_->AsLiteral() != NULL) {
191 kind_ = CONSTANT;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000192 } else {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000193 kind_ = COMPUTED;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000194 }
195}
196
197
198ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000199 Isolate* isolate = Isolate::Current();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000200 emit_store_ = true;
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000201 key_ = new(isolate->zone()) Literal(isolate, value->name());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202 value_ = value;
203 kind_ = is_getter ? GETTER : SETTER;
204}
205
206
ager@chromium.org3811b432009-10-28 14:53:37 +0000207bool ObjectLiteral::Property::IsCompileTimeValue() {
208 return kind_ == CONSTANT ||
209 (kind_ == MATERIALIZED_LITERAL &&
210 CompileTimeValue::IsCompileTimeValue(value_));
211}
212
213
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000214void ObjectLiteral::Property::set_emit_store(bool emit_store) {
215 emit_store_ = emit_store;
216}
217
218
219bool ObjectLiteral::Property::emit_store() {
220 return emit_store_;
221}
222
223
224bool IsEqualString(void* first, void* second) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000225 ASSERT((*reinterpret_cast<String**>(first))->IsString());
226 ASSERT((*reinterpret_cast<String**>(second))->IsString());
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000227 Handle<String> h1(reinterpret_cast<String**>(first));
228 Handle<String> h2(reinterpret_cast<String**>(second));
229 return (*h1)->Equals(*h2);
230}
231
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000232
233bool IsEqualNumber(void* first, void* second) {
234 ASSERT((*reinterpret_cast<Object**>(first))->IsNumber());
235 ASSERT((*reinterpret_cast<Object**>(second))->IsNumber());
236
237 Handle<Object> h1(reinterpret_cast<Object**>(first));
238 Handle<Object> h2(reinterpret_cast<Object**>(second));
239 if (h1->IsSmi()) {
240 return h2->IsSmi() && *h1 == *h2;
241 }
242 if (h2->IsSmi()) return false;
243 Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1);
244 Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2);
245 ASSERT(isfinite(n1->value()));
246 ASSERT(isfinite(n2->value()));
247 return n1->value() == n2->value();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000248}
249
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000250
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000251void ObjectLiteral::CalculateEmitStore() {
252 HashMap properties(&IsEqualString);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000253 HashMap elements(&IsEqualNumber);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000254 for (int i = this->properties()->length() - 1; i >= 0; i--) {
255 ObjectLiteral::Property* property = this->properties()->at(i);
256 Literal* literal = property->key();
257 Handle<Object> handle = literal->handle();
258
259 if (handle->IsNull()) {
260 continue;
261 }
262
263 uint32_t hash;
264 HashMap* table;
265 void* key;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000266 Factory* factory = Isolate::Current()->factory();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000267 if (handle->IsSymbol()) {
268 Handle<String> name(String::cast(*handle));
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000269 if (name->AsArrayIndex(&hash)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000270 Handle<Object> key_handle = factory->NewNumberFromUint(hash);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000271 key = key_handle.location();
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000272 table = &elements;
273 } else {
274 key = name.location();
275 hash = name->Hash();
276 table = &properties;
277 }
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000278 } else if (handle->ToArrayIndex(&hash)) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000279 key = handle.location();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000280 table = &elements;
281 } else {
282 ASSERT(handle->IsNumber());
283 double num = handle->Number();
284 char arr[100];
285 Vector<char> buffer(arr, ARRAY_SIZE(arr));
286 const char* str = DoubleToCString(num, buffer);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000287 Handle<String> name = factory->NewStringFromAscii(CStrVector(str));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000288 key = name.location();
289 hash = name->Hash();
290 table = &properties;
291 }
292 // If the key of a computed property is in the table, do not emit
293 // a store for the property later.
294 if (property->kind() == ObjectLiteral::Property::COMPUTED) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000295 if (table->Lookup(key, hash, false) != NULL) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000296 property->set_emit_store(false);
297 }
298 }
299 // Add key to the table.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000300 table->Lookup(key, hash, true);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000301 }
302}
303
304
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000305void TargetCollector::AddTarget(Label* target) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306 // Add the label to the collector, but discard duplicates.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000307 int length = targets_.length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308 for (int i = 0; i < length; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000309 if (targets_[i] == target) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000310 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000311 targets_.Add(target);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000312}
313
314
ricow@chromium.org65fae842010-08-25 15:26:24 +0000315bool UnaryOperation::ResultOverwriteAllowed() {
316 switch (op_) {
317 case Token::BIT_NOT:
318 case Token::SUB:
319 return true;
320 default:
321 return false;
322 }
323}
324
325
326bool BinaryOperation::ResultOverwriteAllowed() {
327 switch (op_) {
328 case Token::COMMA:
329 case Token::OR:
330 case Token::AND:
331 return false;
332 case Token::BIT_OR:
333 case Token::BIT_XOR:
334 case Token::BIT_AND:
335 case Token::SHL:
336 case Token::SAR:
337 case Token::SHR:
338 case Token::ADD:
339 case Token::SUB:
340 case Token::MUL:
341 case Token::DIV:
342 case Token::MOD:
343 return true;
344 default:
345 UNREACHABLE();
346 }
347 return false;
348}
349
350
ager@chromium.org04921a82011-06-27 13:21:41 +0000351bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
352 Handle<String>* check) {
353 if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return false;
354
355 UnaryOperation* left_unary = left_->AsUnaryOperation();
356 UnaryOperation* right_unary = right_->AsUnaryOperation();
357 Literal* left_literal = left_->AsLiteral();
358 Literal* right_literal = right_->AsLiteral();
359
360 // Check for the pattern: typeof <expression> == <string literal>.
361 if (left_unary != NULL && left_unary->op() == Token::TYPEOF &&
362 right_literal != NULL && right_literal->handle()->IsString()) {
363 *expr = left_unary->expression();
364 *check = Handle<String>::cast(right_literal->handle());
365 return true;
366 }
367
368 // Check for the pattern: <string literal> == typeof <expression>.
369 if (right_unary != NULL && right_unary->op() == Token::TYPEOF &&
370 left_literal != NULL && left_literal->handle()->IsString()) {
371 *expr = right_unary->expression();
372 *check = Handle<String>::cast(left_literal->handle());
373 return true;
374 }
375
376 return false;
377}
378
379
380bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
381 if (op_ != Token::EQ_STRICT) return false;
382
383 UnaryOperation* left_unary = left_->AsUnaryOperation();
384 UnaryOperation* right_unary = right_->AsUnaryOperation();
385
386 // Check for the pattern: <expression> === void <literal>.
387 if (right_unary != NULL && right_unary->op() == Token::VOID &&
388 right_unary->expression()->AsLiteral() != NULL) {
389 *expr = left_;
390 return true;
391 }
392
393 // Check for the pattern: void <literal> === <expression>.
394 if (left_unary != NULL && left_unary->op() == Token::VOID &&
395 left_unary->expression()->AsLiteral() != NULL) {
396 *expr = right_;
397 return true;
398 }
399
400 return false;
401}
402
403
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404// ----------------------------------------------------------------------------
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000405// Inlining support
406
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000407bool Declaration::IsInlineable() const {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000408 return proxy()->var()->IsStackAllocated() && fun() == NULL;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000409}
410
411
412bool TargetCollector::IsInlineable() const {
413 UNREACHABLE();
414 return false;
415}
416
417
418bool Slot::IsInlineable() const {
419 UNREACHABLE();
420 return false;
421}
422
423
424bool ForInStatement::IsInlineable() const {
425 return false;
426}
427
428
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000429bool WithStatement::IsInlineable() const {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000430 return false;
431}
432
433
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000434bool ExitContextStatement::IsInlineable() const {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000435 return false;
436}
437
438
439bool SwitchStatement::IsInlineable() const {
440 return false;
441}
442
443
444bool TryStatement::IsInlineable() const {
445 return false;
446}
447
448
449bool TryCatchStatement::IsInlineable() const {
450 return false;
451}
452
453
454bool TryFinallyStatement::IsInlineable() const {
455 return false;
456}
457
458
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000459bool DebuggerStatement::IsInlineable() const {
460 return false;
461}
462
463
464bool Throw::IsInlineable() const {
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000465 return exception()->IsInlineable();
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000466}
467
468
469bool MaterializedLiteral::IsInlineable() const {
470 // TODO(1322): Allow materialized literals.
471 return false;
472}
473
474
475bool FunctionLiteral::IsInlineable() const {
476 // TODO(1322): Allow materialized literals.
477 return false;
478}
479
480
481bool ThisFunction::IsInlineable() const {
482 return false;
483}
484
485
486bool SharedFunctionInfoLiteral::IsInlineable() const {
487 return false;
488}
489
490
491bool ValidLeftHandSideSentinel::IsInlineable() const {
492 UNREACHABLE();
493 return false;
494}
495
496
497bool ForStatement::IsInlineable() const {
498 return (init() == NULL || init()->IsInlineable())
499 && (cond() == NULL || cond()->IsInlineable())
500 && (next() == NULL || next()->IsInlineable())
501 && body()->IsInlineable();
502}
503
504
505bool WhileStatement::IsInlineable() const {
506 return cond()->IsInlineable()
507 && body()->IsInlineable();
508}
509
510
511bool DoWhileStatement::IsInlineable() const {
512 return cond()->IsInlineable()
513 && body()->IsInlineable();
514}
515
516
517bool ContinueStatement::IsInlineable() const {
518 return true;
519}
520
521
522bool BreakStatement::IsInlineable() const {
523 return true;
524}
525
526
527bool EmptyStatement::IsInlineable() const {
528 return true;
529}
530
531
532bool Literal::IsInlineable() const {
533 return true;
534}
535
536
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000537bool Block::IsInlineable() const {
538 const int count = statements_.length();
539 for (int i = 0; i < count; ++i) {
540 if (!statements_[i]->IsInlineable()) return false;
541 }
542 return true;
543}
544
545
546bool ExpressionStatement::IsInlineable() const {
547 return expression()->IsInlineable();
548}
549
550
551bool IfStatement::IsInlineable() const {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000552 return condition()->IsInlineable()
553 && then_statement()->IsInlineable()
554 && else_statement()->IsInlineable();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000555}
556
557
558bool ReturnStatement::IsInlineable() const {
559 return expression()->IsInlineable();
560}
561
562
563bool Conditional::IsInlineable() const {
564 return condition()->IsInlineable() && then_expression()->IsInlineable() &&
565 else_expression()->IsInlineable();
566}
567
568
569bool VariableProxy::IsInlineable() const {
570 return var()->is_global() || var()->IsStackAllocated();
571}
572
573
574bool Assignment::IsInlineable() const {
575 return target()->IsInlineable() && value()->IsInlineable();
576}
577
578
579bool Property::IsInlineable() const {
580 return obj()->IsInlineable() && key()->IsInlineable();
581}
582
583
584bool Call::IsInlineable() const {
585 if (!expression()->IsInlineable()) return false;
586 const int count = arguments()->length();
587 for (int i = 0; i < count; ++i) {
588 if (!arguments()->at(i)->IsInlineable()) return false;
589 }
590 return true;
591}
592
593
594bool CallNew::IsInlineable() const {
595 if (!expression()->IsInlineable()) return false;
596 const int count = arguments()->length();
597 for (int i = 0; i < count; ++i) {
598 if (!arguments()->at(i)->IsInlineable()) return false;
599 }
600 return true;
601}
602
603
604bool CallRuntime::IsInlineable() const {
ricow@chromium.orgc54d3652011-05-30 09:20:16 +0000605 // Don't try to inline JS runtime calls because we don't (currently) even
606 // optimize them.
607 if (is_jsruntime()) return false;
608 // Don't inline the %_ArgumentsLength or %_Arguments because their
609 // implementation will not work. There is no stack frame to get them
610 // from.
611 if (function()->intrinsic_type == Runtime::INLINE &&
612 (name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
613 name()->IsEqualTo(CStrVector("_Arguments")))) {
614 return false;
615 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000616 const int count = arguments()->length();
617 for (int i = 0; i < count; ++i) {
618 if (!arguments()->at(i)->IsInlineable()) return false;
619 }
620 return true;
621}
622
623
624bool UnaryOperation::IsInlineable() const {
625 return expression()->IsInlineable();
626}
627
628
629bool BinaryOperation::IsInlineable() const {
630 return left()->IsInlineable() && right()->IsInlineable();
631}
632
633
634bool CompareOperation::IsInlineable() const {
635 return left()->IsInlineable() && right()->IsInlineable();
636}
637
638
639bool CompareToNull::IsInlineable() const {
640 return expression()->IsInlineable();
641}
642
643
644bool CountOperation::IsInlineable() const {
645 return expression()->IsInlineable();
646}
647
648
649// ----------------------------------------------------------------------------
650// Recording of type feedback
651
652void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
653 // Record type feedback from the oracle in the AST.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000654 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000655 if (key()->IsPropertyName()) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000656 if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000657 is_array_length_ = true;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000658 } else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) {
ager@chromium.org378b34e2011-01-28 08:04:38 +0000659 is_string_length_ = true;
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000660 } else if (oracle->LoadIsBuiltin(this,
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000661 Builtins::kLoadIC_FunctionPrototype)) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000662 is_function_prototype_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000663 } else {
664 Literal* lit_key = key()->AsLiteral();
665 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
666 Handle<String> name = Handle<String>::cast(lit_key->handle());
667 ZoneMapList* types = oracle->LoadReceiverTypes(this, name);
668 receiver_types_ = types;
669 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000670 } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000671 is_string_access_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000672 } else if (is_monomorphic_) {
673 monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000674 } else if (oracle->LoadIsMegamorphicWithTypeInfo(this)) {
675 receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
676 oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000677 }
678}
679
680
681void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
682 Property* prop = target()->AsProperty();
683 ASSERT(prop != NULL);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000684 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000685 if (prop->key()->IsPropertyName()) {
686 Literal* lit_key = prop->key()->AsLiteral();
687 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
688 Handle<String> name = Handle<String>::cast(lit_key->handle());
689 ZoneMapList* types = oracle->StoreReceiverTypes(this, name);
690 receiver_types_ = types;
691 } else if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000692 // Record receiver type for monomorphic keyed stores.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000693 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000694 } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
695 receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
696 oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000697 }
698}
699
700
701void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000702 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000703 if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000704 // Record receiver type for monomorphic keyed stores.
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000705 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000706 } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
707 receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
708 oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000709 }
710}
711
712
713void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
714 TypeInfo info = oracle->SwitchType(this);
715 if (info.IsSmi()) {
716 compare_type_ = SMI_ONLY;
717 } else if (info.IsNonPrimitive()) {
718 compare_type_ = OBJECT_ONLY;
719 } else {
720 ASSERT(compare_type_ == NONE);
721 }
722}
723
724
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000725static bool CanCallWithoutIC(Handle<JSFunction> target, int arity) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000726 SharedFunctionInfo* info = target->shared();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000727 // If the number of formal parameters of the target function does
728 // not match the number of arguments we're passing, we don't want to
729 // deal with it. Otherwise, we can call it directly.
730 return !target->NeedsArgumentsAdaption() ||
731 info->formal_parameter_count() == arity;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000732}
733
734
735bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000736 if (check_type_ == RECEIVER_MAP_CHECK) {
737 // For primitive checks the holder is set up to point to the
738 // corresponding prototype object, i.e. one step of the algorithm
739 // below has been already performed.
740 // For non-primitive checks we clear it to allow computing targets
741 // for polymorphic calls.
742 holder_ = Handle<JSObject>::null();
743 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000744 while (true) {
745 LookupResult lookup;
746 type->LookupInDescriptors(NULL, *name, &lookup);
747 // If the function wasn't found directly in the map, we start
748 // looking upwards through the prototype chain.
749 if (!lookup.IsFound() && type->prototype()->IsJSObject()) {
750 holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
751 type = Handle<Map>(holder()->map());
752 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
753 target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000754 return CanCallWithoutIC(target_, arguments()->length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000755 } else {
756 return false;
757 }
758 }
759}
760
761
762bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000763 LookupResult* lookup) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000764 target_ = Handle<JSFunction>::null();
765 cell_ = Handle<JSGlobalPropertyCell>::null();
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000766 ASSERT(lookup->IsProperty() &&
767 lookup->type() == NORMAL &&
768 lookup->holder() == *global);
769 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
770 if (cell_->value()->IsJSFunction()) {
771 Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
772 // If the function is in new space we assume it's more likely to
773 // change and thus prefer the general IC code.
774 if (!HEAP->InNewSpace(*candidate) &&
775 CanCallWithoutIC(candidate, arguments()->length())) {
776 target_ = candidate;
777 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000778 }
779 }
780 return false;
781}
782
783
danno@chromium.org40cb8782011-05-25 07:58:50 +0000784void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
785 CallKind call_kind) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000786 Property* property = expression()->AsProperty();
787 ASSERT(property != NULL);
788 // Specialize for the receiver types seen at runtime.
789 Literal* key = property->key()->AsLiteral();
790 ASSERT(key != NULL && key->handle()->IsString());
791 Handle<String> name = Handle<String>::cast(key->handle());
danno@chromium.org40cb8782011-05-25 07:58:50 +0000792 receiver_types_ = oracle->CallReceiverTypes(this, name, call_kind);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000793#ifdef DEBUG
794 if (FLAG_enable_slow_asserts) {
795 if (receiver_types_ != NULL) {
796 int length = receiver_types_->length();
797 for (int i = 0; i < length; i++) {
798 Handle<Map> map = receiver_types_->at(i);
799 ASSERT(!map.is_null() && *map != NULL);
800 }
801 }
802 }
803#endif
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000804 is_monomorphic_ = oracle->CallIsMonomorphic(this);
805 check_type_ = oracle->GetCallCheckType(this);
806 if (is_monomorphic_) {
807 Handle<Map> map;
808 if (receiver_types_ != NULL && receiver_types_->length() > 0) {
809 ASSERT(check_type_ == RECEIVER_MAP_CHECK);
810 map = receiver_types_->at(0);
811 } else {
812 ASSERT(check_type_ != RECEIVER_MAP_CHECK);
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000813 holder_ = Handle<JSObject>(
814 oracle->GetPrototypeForPrimitiveCheck(check_type_));
815 map = Handle<Map>(holder_->map());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000816 }
817 is_monomorphic_ = ComputeTarget(map, name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000818 }
819}
820
821
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000822void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
ager@chromium.org378b34e2011-01-28 08:04:38 +0000823 TypeInfo info = oracle->CompareType(this);
824 if (info.IsSmi()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000825 compare_type_ = SMI_ONLY;
ager@chromium.org378b34e2011-01-28 08:04:38 +0000826 } else if (info.IsNonPrimitive()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000827 compare_type_ = OBJECT_ONLY;
828 } else {
829 ASSERT(compare_type_ == NONE);
830 }
831}
832
833
834// ----------------------------------------------------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000835// Implementation of AstVisitor
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000836
lrn@chromium.org25156de2010-04-06 13:10:27 +0000837bool AstVisitor::CheckStackOverflow() {
838 if (stack_overflow_) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000839 StackLimitCheck check(isolate_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000840 if (!check.HasOverflowed()) return false;
841 return (stack_overflow_ = true);
842}
843
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000844
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000845void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
846 for (int i = 0; i < declarations->length(); i++) {
847 Visit(declarations->at(i));
848 }
849}
850
851
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000852void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000853 for (int i = 0; i < statements->length(); i++) {
854 Visit(statements->at(i));
855 }
856}
857
858
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000859void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000860 for (int i = 0; i < expressions->length(); i++) {
861 // The variable statement visiting code may pass NULL expressions
862 // to this code. Maybe this should be handled by introducing an
863 // undefined expression or literal? Revisit this code if this
864 // changes
865 Expression* expression = expressions->at(i);
866 if (expression != NULL) Visit(expression);
867 }
868}
869
870
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000871// ----------------------------------------------------------------------------
872// Regular expressions
873
874#define MAKE_ACCEPT(Name) \
875 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
876 return visitor->Visit##Name(this, data); \
877 }
878FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
879#undef MAKE_ACCEPT
880
881#define MAKE_TYPE_CASE(Name) \
882 RegExp##Name* RegExpTree::As##Name() { \
883 return NULL; \
884 } \
885 bool RegExpTree::Is##Name() { return false; }
886FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
887#undef MAKE_TYPE_CASE
888
889#define MAKE_TYPE_CASE(Name) \
890 RegExp##Name* RegExp##Name::As##Name() { \
891 return this; \
892 } \
893 bool RegExp##Name::Is##Name() { return true; }
894FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
895#undef MAKE_TYPE_CASE
896
897RegExpEmpty RegExpEmpty::kInstance;
898
899
ager@chromium.org32912102009-01-16 10:38:43 +0000900static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
901 Interval result = Interval::Empty();
902 for (int i = 0; i < children->length(); i++)
903 result = result.Union(children->at(i)->CaptureRegisters());
904 return result;
905}
906
907
908Interval RegExpAlternative::CaptureRegisters() {
909 return ListCaptureRegisters(nodes());
910}
911
912
913Interval RegExpDisjunction::CaptureRegisters() {
914 return ListCaptureRegisters(alternatives());
915}
916
917
918Interval RegExpLookahead::CaptureRegisters() {
919 return body()->CaptureRegisters();
920}
921
922
923Interval RegExpCapture::CaptureRegisters() {
924 Interval self(StartRegister(index()), EndRegister(index()));
925 return self.Union(body()->CaptureRegisters());
926}
927
928
929Interval RegExpQuantifier::CaptureRegisters() {
930 return body()->CaptureRegisters();
931}
932
933
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000934bool RegExpAssertion::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000935 return type() == RegExpAssertion::START_OF_INPUT;
936}
937
938
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000939bool RegExpAssertion::IsAnchoredAtEnd() {
940 return type() == RegExpAssertion::END_OF_INPUT;
941}
942
943
944bool RegExpAlternative::IsAnchoredAtStart() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000945 ZoneList<RegExpTree*>* nodes = this->nodes();
946 for (int i = 0; i < nodes->length(); i++) {
947 RegExpTree* node = nodes->at(i);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000948 if (node->IsAnchoredAtStart()) { return true; }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000949 if (node->max_match() > 0) { return false; }
950 }
951 return false;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000952}
953
954
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000955bool RegExpAlternative::IsAnchoredAtEnd() {
956 ZoneList<RegExpTree*>* nodes = this->nodes();
957 for (int i = nodes->length() - 1; i >= 0; i--) {
958 RegExpTree* node = nodes->at(i);
959 if (node->IsAnchoredAtEnd()) { return true; }
960 if (node->max_match() > 0) { return false; }
961 }
962 return false;
963}
964
965
966bool RegExpDisjunction::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000967 ZoneList<RegExpTree*>* alternatives = this->alternatives();
968 for (int i = 0; i < alternatives->length(); i++) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000969 if (!alternatives->at(i)->IsAnchoredAtStart())
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000970 return false;
971 }
972 return true;
973}
974
975
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000976bool RegExpDisjunction::IsAnchoredAtEnd() {
977 ZoneList<RegExpTree*>* alternatives = this->alternatives();
978 for (int i = 0; i < alternatives->length(); i++) {
979 if (!alternatives->at(i)->IsAnchoredAtEnd())
980 return false;
981 }
982 return true;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000983}
984
985
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000986bool RegExpLookahead::IsAnchoredAtStart() {
987 return is_positive() && body()->IsAnchoredAtStart();
988}
989
990
991bool RegExpCapture::IsAnchoredAtStart() {
992 return body()->IsAnchoredAtStart();
993}
994
995
996bool RegExpCapture::IsAnchoredAtEnd() {
997 return body()->IsAnchoredAtEnd();
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000998}
999
1000
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001001// Convert regular expression trees to a simple sexp representation.
1002// This representation should be different from the input grammar
1003// in as many cases as possible, to make it more difficult for incorrect
1004// parses to look as correct ones which is likely if the input and
1005// output formats are alike.
1006class RegExpUnparser: public RegExpVisitor {
1007 public:
1008 RegExpUnparser();
1009 void VisitCharacterRange(CharacterRange that);
1010 SmartPointer<const char> ToString() { return stream_.ToCString(); }
1011#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
1012 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
1013#undef MAKE_CASE
1014 private:
1015 StringStream* stream() { return &stream_; }
1016 HeapStringAllocator alloc_;
1017 StringStream stream_;
1018};
1019
1020
1021RegExpUnparser::RegExpUnparser() : stream_(&alloc_) {
1022}
1023
1024
1025void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
1026 stream()->Add("(|");
1027 for (int i = 0; i < that->alternatives()->length(); i++) {
1028 stream()->Add(" ");
1029 that->alternatives()->at(i)->Accept(this, data);
1030 }
1031 stream()->Add(")");
1032 return NULL;
1033}
1034
1035
1036void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
1037 stream()->Add("(:");
1038 for (int i = 0; i < that->nodes()->length(); i++) {
1039 stream()->Add(" ");
1040 that->nodes()->at(i)->Accept(this, data);
1041 }
1042 stream()->Add(")");
1043 return NULL;
1044}
1045
1046
1047void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
1048 stream()->Add("%k", that.from());
1049 if (!that.IsSingleton()) {
1050 stream()->Add("-%k", that.to());
1051 }
1052}
1053
1054
1055
1056void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
1057 void* data) {
1058 if (that->is_negated())
1059 stream()->Add("^");
1060 stream()->Add("[");
1061 for (int i = 0; i < that->ranges()->length(); i++) {
1062 if (i > 0) stream()->Add(" ");
1063 VisitCharacterRange(that->ranges()->at(i));
1064 }
1065 stream()->Add("]");
1066 return NULL;
1067}
1068
1069
1070void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
1071 switch (that->type()) {
1072 case RegExpAssertion::START_OF_INPUT:
1073 stream()->Add("@^i");
1074 break;
1075 case RegExpAssertion::END_OF_INPUT:
1076 stream()->Add("@$i");
1077 break;
1078 case RegExpAssertion::START_OF_LINE:
1079 stream()->Add("@^l");
1080 break;
1081 case RegExpAssertion::END_OF_LINE:
1082 stream()->Add("@$l");
1083 break;
1084 case RegExpAssertion::BOUNDARY:
1085 stream()->Add("@b");
1086 break;
1087 case RegExpAssertion::NON_BOUNDARY:
1088 stream()->Add("@B");
1089 break;
1090 }
1091 return NULL;
1092}
1093
1094
1095void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
1096 stream()->Add("'");
1097 Vector<const uc16> chardata = that->data();
1098 for (int i = 0; i < chardata.length(); i++) {
1099 stream()->Add("%k", chardata[i]);
1100 }
1101 stream()->Add("'");
1102 return NULL;
1103}
1104
1105
1106void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
1107 if (that->elements()->length() == 1) {
1108 that->elements()->at(0).data.u_atom->Accept(this, data);
1109 } else {
1110 stream()->Add("(!");
1111 for (int i = 0; i < that->elements()->length(); i++) {
1112 stream()->Add(" ");
1113 that->elements()->at(i).data.u_atom->Accept(this, data);
1114 }
1115 stream()->Add(")");
1116 }
1117 return NULL;
1118}
1119
1120
1121void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
1122 stream()->Add("(# %i ", that->min());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001123 if (that->max() == RegExpTree::kInfinity) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001124 stream()->Add("- ");
1125 } else {
1126 stream()->Add("%i ", that->max());
1127 }
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001128 stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001129 that->body()->Accept(this, data);
1130 stream()->Add(")");
1131 return NULL;
1132}
1133
1134
1135void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
1136 stream()->Add("(^ ");
1137 that->body()->Accept(this, data);
1138 stream()->Add(")");
1139 return NULL;
1140}
1141
1142
1143void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
1144 stream()->Add("(-> ");
1145 stream()->Add(that->is_positive() ? "+ " : "- ");
1146 that->body()->Accept(this, data);
1147 stream()->Add(")");
1148 return NULL;
1149}
1150
1151
1152void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
1153 void* data) {
1154 stream()->Add("(<- %i)", that->index());
1155 return NULL;
1156}
1157
1158
1159void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
1160 stream()->Put('%');
1161 return NULL;
1162}
1163
1164
1165SmartPointer<const char> RegExpTree::ToString() {
1166 RegExpUnparser unparser;
1167 Accept(&unparser, NULL);
1168 return unparser.ToString();
1169}
1170
1171
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001172RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
1173 : alternatives_(alternatives) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001174 ASSERT(alternatives->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001175 RegExpTree* first_alternative = alternatives->at(0);
1176 min_match_ = first_alternative->min_match();
1177 max_match_ = first_alternative->max_match();
1178 for (int i = 1; i < alternatives->length(); i++) {
1179 RegExpTree* alternative = alternatives->at(i);
1180 min_match_ = Min(min_match_, alternative->min_match());
1181 max_match_ = Max(max_match_, alternative->max_match());
1182 }
1183}
1184
1185
1186RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
1187 : nodes_(nodes) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001188 ASSERT(nodes->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001189 min_match_ = 0;
1190 max_match_ = 0;
1191 for (int i = 0; i < nodes->length(); i++) {
1192 RegExpTree* node = nodes->at(i);
1193 min_match_ += node->min_match();
1194 int node_max_match = node->max_match();
1195 if (kInfinity - max_match_ < node_max_match) {
1196 max_match_ = kInfinity;
1197 } else {
1198 max_match_ += node->max_match();
1199 }
1200 }
1201}
1202
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001203
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001204CaseClause::CaseClause(Isolate* isolate,
1205 Expression* label,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001206 ZoneList<Statement*>* statements,
1207 int pos)
1208 : label_(label),
1209 statements_(statements),
1210 position_(pos),
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001211 compare_type_(NONE),
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001212 compare_id_(AstNode::GetNextId(isolate)),
1213 entry_id_(AstNode::GetNextId(isolate)) {
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001214}
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001215
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001216} } // namespace v8::internal