blob: 03df229963ec00771500449589e04640e657c2df [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()
40 : this_proxy_(true),
41 identifier_proxy_(false),
42 valid_left_hand_side_sentinel_(),
43 this_property_(&this_proxy_, NULL, 0),
44 call_sentinel_(NULL, NULL, 0) {
45}
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
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000075VariableProxy::VariableProxy(Variable* var)
76 : name_(var->name()),
77 var_(NULL), // Will be set by the call to BindTo.
78 is_this_(var->is_this()),
79 inside_with_(false),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000080 is_trivial_(false),
81 position_(RelocInfo::kNoPosition) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000082 BindTo(var);
83}
84
85
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000086VariableProxy::VariableProxy(Handle<String> name,
87 bool is_this,
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000088 bool inside_with,
89 int position)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000090 : name_(name),
91 var_(NULL),
92 is_this_(is_this),
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000093 inside_with_(inside_with),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000094 is_trivial_(false),
95 position_(position) {
96 // Names must be canonicalized for fast equality checks.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000097 ASSERT(name->IsSymbol());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000098}
99
100
101VariableProxy::VariableProxy(bool is_this)
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000102 : var_(NULL),
103 is_this_(is_this),
104 inside_with_(false),
105 is_trivial_(false) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000106}
107
108
109void VariableProxy::BindTo(Variable* var) {
110 ASSERT(var_ == NULL); // must be bound only once
111 ASSERT(var != NULL); // must bind
112 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
113 // Ideally CONST-ness should match. However, this is very hard to achieve
114 // because we don't know the exact semantics of conflicting (const and
115 // non-const) multiple variable declarations, const vars introduced via
116 // eval() etc. Const-ness and variable declarations are a complete mess
117 // in JS. Sigh...
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000118 var_ = var;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000119 var->set_is_used(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000120}
121
122
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000123Assignment::Assignment(Token::Value op,
124 Expression* target,
125 Expression* value,
126 int pos)
127 : op_(op),
128 target_(target),
129 value_(value),
130 pos_(pos),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000131 binary_operation_(NULL),
132 compound_load_id_(kNoNumber),
133 assignment_id_(GetNextId()),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000134 block_start_(false),
135 block_end_(false),
136 is_monomorphic_(false),
137 receiver_types_(NULL) {
138 ASSERT(Token::IsAssignmentOp(op));
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000139 if (is_compound()) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000140 binary_operation_ =
141 new BinaryOperation(binary_op(), target, value, pos + 1);
142 compound_load_id_ = GetNextId();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143 }
144}
145
146
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147Token::Value Assignment::binary_op() const {
148 switch (op_) {
149 case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
150 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
151 case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
152 case Token::ASSIGN_SHL: return Token::SHL;
153 case Token::ASSIGN_SAR: return Token::SAR;
154 case Token::ASSIGN_SHR: return Token::SHR;
155 case Token::ASSIGN_ADD: return Token::ADD;
156 case Token::ASSIGN_SUB: return Token::SUB;
157 case Token::ASSIGN_MUL: return Token::MUL;
158 case Token::ASSIGN_DIV: return Token::DIV;
159 case Token::ASSIGN_MOD: return Token::MOD;
160 default: UNREACHABLE();
161 }
162 return Token::ILLEGAL;
163}
164
165
166bool FunctionLiteral::AllowsLazyCompilation() {
167 return scope()->AllowsLazyCompilation();
168}
169
170
171ObjectLiteral::Property::Property(Literal* key, Expression* value) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000172 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173 key_ = key;
174 value_ = value;
175 Object* k = *key->handle();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000176 if (k->IsSymbol() && HEAP->Proto_symbol()->Equals(String::cast(k))) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177 kind_ = PROTOTYPE;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000178 } else if (value_->AsMaterializedLiteral() != NULL) {
179 kind_ = MATERIALIZED_LITERAL;
180 } else if (value_->AsLiteral() != NULL) {
181 kind_ = CONSTANT;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 } else {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000183 kind_ = COMPUTED;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000184 }
185}
186
187
188ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000189 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000190 key_ = new Literal(value->name());
191 value_ = value;
192 kind_ = is_getter ? GETTER : SETTER;
193}
194
195
ager@chromium.org3811b432009-10-28 14:53:37 +0000196bool ObjectLiteral::Property::IsCompileTimeValue() {
197 return kind_ == CONSTANT ||
198 (kind_ == MATERIALIZED_LITERAL &&
199 CompileTimeValue::IsCompileTimeValue(value_));
200}
201
202
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000203void ObjectLiteral::Property::set_emit_store(bool emit_store) {
204 emit_store_ = emit_store;
205}
206
207
208bool ObjectLiteral::Property::emit_store() {
209 return emit_store_;
210}
211
212
213bool IsEqualString(void* first, void* second) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000214 ASSERT((*reinterpret_cast<String**>(first))->IsString());
215 ASSERT((*reinterpret_cast<String**>(second))->IsString());
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000216 Handle<String> h1(reinterpret_cast<String**>(first));
217 Handle<String> h2(reinterpret_cast<String**>(second));
218 return (*h1)->Equals(*h2);
219}
220
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000221
222bool IsEqualNumber(void* first, void* second) {
223 ASSERT((*reinterpret_cast<Object**>(first))->IsNumber());
224 ASSERT((*reinterpret_cast<Object**>(second))->IsNumber());
225
226 Handle<Object> h1(reinterpret_cast<Object**>(first));
227 Handle<Object> h2(reinterpret_cast<Object**>(second));
228 if (h1->IsSmi()) {
229 return h2->IsSmi() && *h1 == *h2;
230 }
231 if (h2->IsSmi()) return false;
232 Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1);
233 Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2);
234 ASSERT(isfinite(n1->value()));
235 ASSERT(isfinite(n2->value()));
236 return n1->value() == n2->value();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000237}
238
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000239
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000240void ObjectLiteral::CalculateEmitStore() {
241 HashMap properties(&IsEqualString);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000242 HashMap elements(&IsEqualNumber);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000243 for (int i = this->properties()->length() - 1; i >= 0; i--) {
244 ObjectLiteral::Property* property = this->properties()->at(i);
245 Literal* literal = property->key();
246 Handle<Object> handle = literal->handle();
247
248 if (handle->IsNull()) {
249 continue;
250 }
251
252 uint32_t hash;
253 HashMap* table;
254 void* key;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000255 Factory* factory = Isolate::Current()->factory();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000256 if (handle->IsSymbol()) {
257 Handle<String> name(String::cast(*handle));
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000258 if (name->AsArrayIndex(&hash)) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000259 Handle<Object> key_handle = factory->NewNumberFromUint(hash);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000260 key = key_handle.location();
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000261 table = &elements;
262 } else {
263 key = name.location();
264 hash = name->Hash();
265 table = &properties;
266 }
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000267 } else if (handle->ToArrayIndex(&hash)) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000268 key = handle.location();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000269 table = &elements;
270 } else {
271 ASSERT(handle->IsNumber());
272 double num = handle->Number();
273 char arr[100];
274 Vector<char> buffer(arr, ARRAY_SIZE(arr));
275 const char* str = DoubleToCString(num, buffer);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000276 Handle<String> name = factory->NewStringFromAscii(CStrVector(str));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000277 key = name.location();
278 hash = name->Hash();
279 table = &properties;
280 }
281 // If the key of a computed property is in the table, do not emit
282 // a store for the property later.
283 if (property->kind() == ObjectLiteral::Property::COMPUTED) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000284 if (table->Lookup(key, hash, false) != NULL) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000285 property->set_emit_store(false);
286 }
287 }
288 // Add key to the table.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000289 table->Lookup(key, hash, true);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000290 }
291}
292
293
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000294void TargetCollector::AddTarget(Label* target) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000295 // Add the label to the collector, but discard duplicates.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000296 int length = targets_.length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297 for (int i = 0; i < length; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000298 if (targets_[i] == target) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000299 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000300 targets_.Add(target);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000301}
302
303
ricow@chromium.org65fae842010-08-25 15:26:24 +0000304bool UnaryOperation::ResultOverwriteAllowed() {
305 switch (op_) {
306 case Token::BIT_NOT:
307 case Token::SUB:
308 return true;
309 default:
310 return false;
311 }
312}
313
314
315bool BinaryOperation::ResultOverwriteAllowed() {
316 switch (op_) {
317 case Token::COMMA:
318 case Token::OR:
319 case Token::AND:
320 return false;
321 case Token::BIT_OR:
322 case Token::BIT_XOR:
323 case Token::BIT_AND:
324 case Token::SHL:
325 case Token::SAR:
326 case Token::SHR:
327 case Token::ADD:
328 case Token::SUB:
329 case Token::MUL:
330 case Token::DIV:
331 case Token::MOD:
332 return true;
333 default:
334 UNREACHABLE();
335 }
336 return false;
337}
338
339
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000340// ----------------------------------------------------------------------------
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000341// Inlining support
342
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000343bool Declaration::IsInlineable() const {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000344 return proxy()->var()->IsStackAllocated() && fun() == NULL;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000345}
346
347
348bool TargetCollector::IsInlineable() const {
349 UNREACHABLE();
350 return false;
351}
352
353
354bool Slot::IsInlineable() const {
355 UNREACHABLE();
356 return false;
357}
358
359
360bool ForInStatement::IsInlineable() const {
361 return false;
362}
363
364
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000365bool EnterWithContextStatement::IsInlineable() const {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000366 return false;
367}
368
369
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000370bool ExitContextStatement::IsInlineable() const {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000371 return false;
372}
373
374
375bool SwitchStatement::IsInlineable() const {
376 return false;
377}
378
379
380bool TryStatement::IsInlineable() const {
381 return false;
382}
383
384
385bool TryCatchStatement::IsInlineable() const {
386 return false;
387}
388
389
390bool TryFinallyStatement::IsInlineable() const {
391 return false;
392}
393
394
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000395bool DebuggerStatement::IsInlineable() const {
396 return false;
397}
398
399
400bool Throw::IsInlineable() const {
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000401 return exception()->IsInlineable();
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000402}
403
404
405bool MaterializedLiteral::IsInlineable() const {
406 // TODO(1322): Allow materialized literals.
407 return false;
408}
409
410
411bool FunctionLiteral::IsInlineable() const {
412 // TODO(1322): Allow materialized literals.
413 return false;
414}
415
416
417bool ThisFunction::IsInlineable() const {
418 return false;
419}
420
421
422bool SharedFunctionInfoLiteral::IsInlineable() const {
423 return false;
424}
425
426
427bool ValidLeftHandSideSentinel::IsInlineable() const {
428 UNREACHABLE();
429 return false;
430}
431
432
433bool ForStatement::IsInlineable() const {
434 return (init() == NULL || init()->IsInlineable())
435 && (cond() == NULL || cond()->IsInlineable())
436 && (next() == NULL || next()->IsInlineable())
437 && body()->IsInlineable();
438}
439
440
441bool WhileStatement::IsInlineable() const {
442 return cond()->IsInlineable()
443 && body()->IsInlineable();
444}
445
446
447bool DoWhileStatement::IsInlineable() const {
448 return cond()->IsInlineable()
449 && body()->IsInlineable();
450}
451
452
453bool ContinueStatement::IsInlineable() const {
454 return true;
455}
456
457
458bool BreakStatement::IsInlineable() const {
459 return true;
460}
461
462
463bool EmptyStatement::IsInlineable() const {
464 return true;
465}
466
467
468bool Literal::IsInlineable() const {
469 return true;
470}
471
472
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000473bool Block::IsInlineable() const {
474 const int count = statements_.length();
475 for (int i = 0; i < count; ++i) {
476 if (!statements_[i]->IsInlineable()) return false;
477 }
478 return true;
479}
480
481
482bool ExpressionStatement::IsInlineable() const {
483 return expression()->IsInlineable();
484}
485
486
487bool IfStatement::IsInlineable() const {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000488 return condition()->IsInlineable()
489 && then_statement()->IsInlineable()
490 && else_statement()->IsInlineable();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000491}
492
493
494bool ReturnStatement::IsInlineable() const {
495 return expression()->IsInlineable();
496}
497
498
499bool Conditional::IsInlineable() const {
500 return condition()->IsInlineable() && then_expression()->IsInlineable() &&
501 else_expression()->IsInlineable();
502}
503
504
505bool VariableProxy::IsInlineable() const {
506 return var()->is_global() || var()->IsStackAllocated();
507}
508
509
510bool Assignment::IsInlineable() const {
511 return target()->IsInlineable() && value()->IsInlineable();
512}
513
514
515bool Property::IsInlineable() const {
516 return obj()->IsInlineable() && key()->IsInlineable();
517}
518
519
520bool Call::IsInlineable() const {
521 if (!expression()->IsInlineable()) return false;
522 const int count = arguments()->length();
523 for (int i = 0; i < count; ++i) {
524 if (!arguments()->at(i)->IsInlineable()) return false;
525 }
526 return true;
527}
528
529
530bool CallNew::IsInlineable() const {
531 if (!expression()->IsInlineable()) return false;
532 const int count = arguments()->length();
533 for (int i = 0; i < count; ++i) {
534 if (!arguments()->at(i)->IsInlineable()) return false;
535 }
536 return true;
537}
538
539
540bool CallRuntime::IsInlineable() const {
ricow@chromium.orgc54d3652011-05-30 09:20:16 +0000541 // Don't try to inline JS runtime calls because we don't (currently) even
542 // optimize them.
543 if (is_jsruntime()) return false;
544 // Don't inline the %_ArgumentsLength or %_Arguments because their
545 // implementation will not work. There is no stack frame to get them
546 // from.
547 if (function()->intrinsic_type == Runtime::INLINE &&
548 (name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
549 name()->IsEqualTo(CStrVector("_Arguments")))) {
550 return false;
551 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000552 const int count = arguments()->length();
553 for (int i = 0; i < count; ++i) {
554 if (!arguments()->at(i)->IsInlineable()) return false;
555 }
556 return true;
557}
558
559
560bool UnaryOperation::IsInlineable() const {
561 return expression()->IsInlineable();
562}
563
564
565bool BinaryOperation::IsInlineable() const {
566 return left()->IsInlineable() && right()->IsInlineable();
567}
568
569
570bool CompareOperation::IsInlineable() const {
571 return left()->IsInlineable() && right()->IsInlineable();
572}
573
574
575bool CompareToNull::IsInlineable() const {
576 return expression()->IsInlineable();
577}
578
579
580bool CountOperation::IsInlineable() const {
581 return expression()->IsInlineable();
582}
583
584
585// ----------------------------------------------------------------------------
586// Recording of type feedback
587
588void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
589 // Record type feedback from the oracle in the AST.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000590 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000591 if (key()->IsPropertyName()) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000592 if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000593 is_array_length_ = true;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000594 } else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) {
ager@chromium.org378b34e2011-01-28 08:04:38 +0000595 is_string_length_ = true;
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000596 } else if (oracle->LoadIsBuiltin(this,
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000597 Builtins::kLoadIC_FunctionPrototype)) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000598 is_function_prototype_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000599 } else {
600 Literal* lit_key = key()->AsLiteral();
601 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
602 Handle<String> name = Handle<String>::cast(lit_key->handle());
603 ZoneMapList* types = oracle->LoadReceiverTypes(this, name);
604 receiver_types_ = types;
605 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000606 } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000607 is_string_access_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000608 } else if (is_monomorphic_) {
609 monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
610 }
611}
612
613
614void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
615 Property* prop = target()->AsProperty();
616 ASSERT(prop != NULL);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000617 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000618 if (prop->key()->IsPropertyName()) {
619 Literal* lit_key = prop->key()->AsLiteral();
620 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
621 Handle<String> name = Handle<String>::cast(lit_key->handle());
622 ZoneMapList* types = oracle->StoreReceiverTypes(this, name);
623 receiver_types_ = types;
624 } else if (is_monomorphic_) {
625 // Record receiver type for monomorphic keyed loads.
626 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000627 }
628}
629
630
631void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000632 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000633 if (is_monomorphic_) {
634 // Record receiver type for monomorphic keyed loads.
635 monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000636 }
637}
638
639
640void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
641 TypeInfo info = oracle->SwitchType(this);
642 if (info.IsSmi()) {
643 compare_type_ = SMI_ONLY;
644 } else if (info.IsNonPrimitive()) {
645 compare_type_ = OBJECT_ONLY;
646 } else {
647 ASSERT(compare_type_ == NONE);
648 }
649}
650
651
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000652static bool CanCallWithoutIC(Handle<JSFunction> target, int arity) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000653 SharedFunctionInfo* info = target->shared();
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000654 // If the number of formal parameters of the target function does
655 // not match the number of arguments we're passing, we don't want to
656 // deal with it. Otherwise, we can call it directly.
657 return !target->NeedsArgumentsAdaption() ||
658 info->formal_parameter_count() == arity;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000659}
660
661
662bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000663 if (check_type_ == RECEIVER_MAP_CHECK) {
664 // For primitive checks the holder is set up to point to the
665 // corresponding prototype object, i.e. one step of the algorithm
666 // below has been already performed.
667 // For non-primitive checks we clear it to allow computing targets
668 // for polymorphic calls.
669 holder_ = Handle<JSObject>::null();
670 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000671 while (true) {
672 LookupResult lookup;
673 type->LookupInDescriptors(NULL, *name, &lookup);
674 // If the function wasn't found directly in the map, we start
675 // looking upwards through the prototype chain.
676 if (!lookup.IsFound() && type->prototype()->IsJSObject()) {
677 holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
678 type = Handle<Map>(holder()->map());
679 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
680 target_ = Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000681 return CanCallWithoutIC(target_, arguments()->length());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000682 } else {
683 return false;
684 }
685 }
686}
687
688
689bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000690 LookupResult* lookup) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000691 target_ = Handle<JSFunction>::null();
692 cell_ = Handle<JSGlobalPropertyCell>::null();
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000693 ASSERT(lookup->IsProperty() &&
694 lookup->type() == NORMAL &&
695 lookup->holder() == *global);
696 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
697 if (cell_->value()->IsJSFunction()) {
698 Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
699 // If the function is in new space we assume it's more likely to
700 // change and thus prefer the general IC code.
701 if (!HEAP->InNewSpace(*candidate) &&
702 CanCallWithoutIC(candidate, arguments()->length())) {
703 target_ = candidate;
704 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000705 }
706 }
707 return false;
708}
709
710
danno@chromium.org40cb8782011-05-25 07:58:50 +0000711void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
712 CallKind call_kind) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000713 Property* property = expression()->AsProperty();
714 ASSERT(property != NULL);
715 // Specialize for the receiver types seen at runtime.
716 Literal* key = property->key()->AsLiteral();
717 ASSERT(key != NULL && key->handle()->IsString());
718 Handle<String> name = Handle<String>::cast(key->handle());
danno@chromium.org40cb8782011-05-25 07:58:50 +0000719 receiver_types_ = oracle->CallReceiverTypes(this, name, call_kind);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000720#ifdef DEBUG
721 if (FLAG_enable_slow_asserts) {
722 if (receiver_types_ != NULL) {
723 int length = receiver_types_->length();
724 for (int i = 0; i < length; i++) {
725 Handle<Map> map = receiver_types_->at(i);
726 ASSERT(!map.is_null() && *map != NULL);
727 }
728 }
729 }
730#endif
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000731 is_monomorphic_ = oracle->CallIsMonomorphic(this);
732 check_type_ = oracle->GetCallCheckType(this);
733 if (is_monomorphic_) {
734 Handle<Map> map;
735 if (receiver_types_ != NULL && receiver_types_->length() > 0) {
736 ASSERT(check_type_ == RECEIVER_MAP_CHECK);
737 map = receiver_types_->at(0);
738 } else {
739 ASSERT(check_type_ != RECEIVER_MAP_CHECK);
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000740 holder_ = Handle<JSObject>(
741 oracle->GetPrototypeForPrimitiveCheck(check_type_));
742 map = Handle<Map>(holder_->map());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000743 }
744 is_monomorphic_ = ComputeTarget(map, name);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000745 }
746}
747
748
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000749void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
ager@chromium.org378b34e2011-01-28 08:04:38 +0000750 TypeInfo info = oracle->CompareType(this);
751 if (info.IsSmi()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000752 compare_type_ = SMI_ONLY;
ager@chromium.org378b34e2011-01-28 08:04:38 +0000753 } else if (info.IsNonPrimitive()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000754 compare_type_ = OBJECT_ONLY;
755 } else {
756 ASSERT(compare_type_ == NONE);
757 }
758}
759
760
761// ----------------------------------------------------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000762// Implementation of AstVisitor
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000763
lrn@chromium.org25156de2010-04-06 13:10:27 +0000764bool AstVisitor::CheckStackOverflow() {
765 if (stack_overflow_) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000766 StackLimitCheck check(isolate_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000767 if (!check.HasOverflowed()) return false;
768 return (stack_overflow_ = true);
769}
770
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000771
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000772void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
773 for (int i = 0; i < declarations->length(); i++) {
774 Visit(declarations->at(i));
775 }
776}
777
778
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000779void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000780 for (int i = 0; i < statements->length(); i++) {
781 Visit(statements->at(i));
782 }
783}
784
785
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000786void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787 for (int i = 0; i < expressions->length(); i++) {
788 // The variable statement visiting code may pass NULL expressions
789 // to this code. Maybe this should be handled by introducing an
790 // undefined expression or literal? Revisit this code if this
791 // changes
792 Expression* expression = expressions->at(i);
793 if (expression != NULL) Visit(expression);
794 }
795}
796
797
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000798// ----------------------------------------------------------------------------
799// Regular expressions
800
801#define MAKE_ACCEPT(Name) \
802 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
803 return visitor->Visit##Name(this, data); \
804 }
805FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
806#undef MAKE_ACCEPT
807
808#define MAKE_TYPE_CASE(Name) \
809 RegExp##Name* RegExpTree::As##Name() { \
810 return NULL; \
811 } \
812 bool RegExpTree::Is##Name() { return false; }
813FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
814#undef MAKE_TYPE_CASE
815
816#define MAKE_TYPE_CASE(Name) \
817 RegExp##Name* RegExp##Name::As##Name() { \
818 return this; \
819 } \
820 bool RegExp##Name::Is##Name() { return true; }
821FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
822#undef MAKE_TYPE_CASE
823
824RegExpEmpty RegExpEmpty::kInstance;
825
826
ager@chromium.org32912102009-01-16 10:38:43 +0000827static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
828 Interval result = Interval::Empty();
829 for (int i = 0; i < children->length(); i++)
830 result = result.Union(children->at(i)->CaptureRegisters());
831 return result;
832}
833
834
835Interval RegExpAlternative::CaptureRegisters() {
836 return ListCaptureRegisters(nodes());
837}
838
839
840Interval RegExpDisjunction::CaptureRegisters() {
841 return ListCaptureRegisters(alternatives());
842}
843
844
845Interval RegExpLookahead::CaptureRegisters() {
846 return body()->CaptureRegisters();
847}
848
849
850Interval RegExpCapture::CaptureRegisters() {
851 Interval self(StartRegister(index()), EndRegister(index()));
852 return self.Union(body()->CaptureRegisters());
853}
854
855
856Interval RegExpQuantifier::CaptureRegisters() {
857 return body()->CaptureRegisters();
858}
859
860
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000861bool RegExpAssertion::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000862 return type() == RegExpAssertion::START_OF_INPUT;
863}
864
865
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000866bool RegExpAssertion::IsAnchoredAtEnd() {
867 return type() == RegExpAssertion::END_OF_INPUT;
868}
869
870
871bool RegExpAlternative::IsAnchoredAtStart() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000872 ZoneList<RegExpTree*>* nodes = this->nodes();
873 for (int i = 0; i < nodes->length(); i++) {
874 RegExpTree* node = nodes->at(i);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000875 if (node->IsAnchoredAtStart()) { return true; }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000876 if (node->max_match() > 0) { return false; }
877 }
878 return false;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000879}
880
881
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000882bool RegExpAlternative::IsAnchoredAtEnd() {
883 ZoneList<RegExpTree*>* nodes = this->nodes();
884 for (int i = nodes->length() - 1; i >= 0; i--) {
885 RegExpTree* node = nodes->at(i);
886 if (node->IsAnchoredAtEnd()) { return true; }
887 if (node->max_match() > 0) { return false; }
888 }
889 return false;
890}
891
892
893bool RegExpDisjunction::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000894 ZoneList<RegExpTree*>* alternatives = this->alternatives();
895 for (int i = 0; i < alternatives->length(); i++) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000896 if (!alternatives->at(i)->IsAnchoredAtStart())
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000897 return false;
898 }
899 return true;
900}
901
902
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000903bool RegExpDisjunction::IsAnchoredAtEnd() {
904 ZoneList<RegExpTree*>* alternatives = this->alternatives();
905 for (int i = 0; i < alternatives->length(); i++) {
906 if (!alternatives->at(i)->IsAnchoredAtEnd())
907 return false;
908 }
909 return true;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000910}
911
912
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000913bool RegExpLookahead::IsAnchoredAtStart() {
914 return is_positive() && body()->IsAnchoredAtStart();
915}
916
917
918bool RegExpCapture::IsAnchoredAtStart() {
919 return body()->IsAnchoredAtStart();
920}
921
922
923bool RegExpCapture::IsAnchoredAtEnd() {
924 return body()->IsAnchoredAtEnd();
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000925}
926
927
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000928// Convert regular expression trees to a simple sexp representation.
929// This representation should be different from the input grammar
930// in as many cases as possible, to make it more difficult for incorrect
931// parses to look as correct ones which is likely if the input and
932// output formats are alike.
933class RegExpUnparser: public RegExpVisitor {
934 public:
935 RegExpUnparser();
936 void VisitCharacterRange(CharacterRange that);
937 SmartPointer<const char> ToString() { return stream_.ToCString(); }
938#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
939 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
940#undef MAKE_CASE
941 private:
942 StringStream* stream() { return &stream_; }
943 HeapStringAllocator alloc_;
944 StringStream stream_;
945};
946
947
948RegExpUnparser::RegExpUnparser() : stream_(&alloc_) {
949}
950
951
952void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
953 stream()->Add("(|");
954 for (int i = 0; i < that->alternatives()->length(); i++) {
955 stream()->Add(" ");
956 that->alternatives()->at(i)->Accept(this, data);
957 }
958 stream()->Add(")");
959 return NULL;
960}
961
962
963void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
964 stream()->Add("(:");
965 for (int i = 0; i < that->nodes()->length(); i++) {
966 stream()->Add(" ");
967 that->nodes()->at(i)->Accept(this, data);
968 }
969 stream()->Add(")");
970 return NULL;
971}
972
973
974void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
975 stream()->Add("%k", that.from());
976 if (!that.IsSingleton()) {
977 stream()->Add("-%k", that.to());
978 }
979}
980
981
982
983void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
984 void* data) {
985 if (that->is_negated())
986 stream()->Add("^");
987 stream()->Add("[");
988 for (int i = 0; i < that->ranges()->length(); i++) {
989 if (i > 0) stream()->Add(" ");
990 VisitCharacterRange(that->ranges()->at(i));
991 }
992 stream()->Add("]");
993 return NULL;
994}
995
996
997void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
998 switch (that->type()) {
999 case RegExpAssertion::START_OF_INPUT:
1000 stream()->Add("@^i");
1001 break;
1002 case RegExpAssertion::END_OF_INPUT:
1003 stream()->Add("@$i");
1004 break;
1005 case RegExpAssertion::START_OF_LINE:
1006 stream()->Add("@^l");
1007 break;
1008 case RegExpAssertion::END_OF_LINE:
1009 stream()->Add("@$l");
1010 break;
1011 case RegExpAssertion::BOUNDARY:
1012 stream()->Add("@b");
1013 break;
1014 case RegExpAssertion::NON_BOUNDARY:
1015 stream()->Add("@B");
1016 break;
1017 }
1018 return NULL;
1019}
1020
1021
1022void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
1023 stream()->Add("'");
1024 Vector<const uc16> chardata = that->data();
1025 for (int i = 0; i < chardata.length(); i++) {
1026 stream()->Add("%k", chardata[i]);
1027 }
1028 stream()->Add("'");
1029 return NULL;
1030}
1031
1032
1033void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
1034 if (that->elements()->length() == 1) {
1035 that->elements()->at(0).data.u_atom->Accept(this, data);
1036 } else {
1037 stream()->Add("(!");
1038 for (int i = 0; i < that->elements()->length(); i++) {
1039 stream()->Add(" ");
1040 that->elements()->at(i).data.u_atom->Accept(this, data);
1041 }
1042 stream()->Add(")");
1043 }
1044 return NULL;
1045}
1046
1047
1048void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
1049 stream()->Add("(# %i ", that->min());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001050 if (that->max() == RegExpTree::kInfinity) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001051 stream()->Add("- ");
1052 } else {
1053 stream()->Add("%i ", that->max());
1054 }
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001055 stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
ager@chromium.orga74f0da2008-12-03 16:05:52 +00001056 that->body()->Accept(this, data);
1057 stream()->Add(")");
1058 return NULL;
1059}
1060
1061
1062void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
1063 stream()->Add("(^ ");
1064 that->body()->Accept(this, data);
1065 stream()->Add(")");
1066 return NULL;
1067}
1068
1069
1070void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
1071 stream()->Add("(-> ");
1072 stream()->Add(that->is_positive() ? "+ " : "- ");
1073 that->body()->Accept(this, data);
1074 stream()->Add(")");
1075 return NULL;
1076}
1077
1078
1079void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
1080 void* data) {
1081 stream()->Add("(<- %i)", that->index());
1082 return NULL;
1083}
1084
1085
1086void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
1087 stream()->Put('%');
1088 return NULL;
1089}
1090
1091
1092SmartPointer<const char> RegExpTree::ToString() {
1093 RegExpUnparser unparser;
1094 Accept(&unparser, NULL);
1095 return unparser.ToString();
1096}
1097
1098
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001099RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
1100 : alternatives_(alternatives) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001101 ASSERT(alternatives->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001102 RegExpTree* first_alternative = alternatives->at(0);
1103 min_match_ = first_alternative->min_match();
1104 max_match_ = first_alternative->max_match();
1105 for (int i = 1; i < alternatives->length(); i++) {
1106 RegExpTree* alternative = alternatives->at(i);
1107 min_match_ = Min(min_match_, alternative->min_match());
1108 max_match_ = Max(max_match_, alternative->max_match());
1109 }
1110}
1111
1112
1113RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
1114 : nodes_(nodes) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001115 ASSERT(nodes->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001116 min_match_ = 0;
1117 max_match_ = 0;
1118 for (int i = 0; i < nodes->length(); i++) {
1119 RegExpTree* node = nodes->at(i);
1120 min_match_ += node->min_match();
1121 int node_max_match = node->max_match();
1122 if (kInfinity - max_match_ < node_max_match) {
1123 max_match_ = kInfinity;
1124 } else {
1125 max_match_ += node->max_match();
1126 }
1127 }
1128}
1129
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001130
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001131CaseClause::CaseClause(Expression* label,
1132 ZoneList<Statement*>* statements,
1133 int pos)
1134 : label_(label),
1135 statements_(statements),
1136 position_(pos),
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001137 compare_type_(NONE),
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001138 compare_id_(AstNode::GetNextId()),
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001139 entry_id_(AstNode::GetNextId()) {
1140}
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001141
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001142} } // namespace v8::internal