blob: 627e65a039dfec46f09cb92fbf340ee0f7513817 [file] [log] [blame]
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001// Copyright 2012 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000028#include "ast.h"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000029
30#include <math.h> // For isfinite.
31#include "builtins.h"
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +000032#include "code-stubs.h"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000033#include "conversions.h"
34#include "hashmap.h"
ager@chromium.org3811b432009-10-28 14:53:37 +000035#include "parser.h"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000036#include "property-details.h"
37#include "property.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038#include "scopes.h"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000039#include "string-stream.h"
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000040#include "type-info.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041
kasperl@chromium.org71affb52009-05-26 05:44:31 +000042namespace v8 {
43namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045// ----------------------------------------------------------------------------
46// All the Accept member functions for each syntax tree node type.
47
lrn@chromium.org25156de2010-04-06 13:10:27 +000048#define DECL_ACCEPT(type) \
49 void type::Accept(AstVisitor* v) { v->Visit##type(this); }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000050AST_NODE_LIST(DECL_ACCEPT)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051#undef DECL_ACCEPT
52
53
54// ----------------------------------------------------------------------------
55// Implementation of other node functionality.
56
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000057
58bool Expression::IsSmiLiteral() {
59 return AsLiteral() != NULL && AsLiteral()->handle()->IsSmi();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000060}
61
62
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000063bool Expression::IsStringLiteral() {
64 return AsLiteral() != NULL && AsLiteral()->handle()->IsString();
65}
66
67
68bool Expression::IsNullLiteral() {
69 return AsLiteral() != NULL && AsLiteral()->handle()->IsNull();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000070}
71
72
rossberg@chromium.org717967f2011-07-20 13:44:42 +000073VariableProxy::VariableProxy(Isolate* isolate, Variable* var)
74 : Expression(isolate),
75 name_(var->name()),
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000076 var_(NULL), // Will be set by the call to BindTo.
77 is_this_(var->is_this()),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000078 is_trivial_(false),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +000079 is_lvalue_(false),
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000080 position_(RelocInfo::kNoPosition),
81 interface_(var->interface()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000082 BindTo(var);
83}
84
85
rossberg@chromium.org717967f2011-07-20 13:44:42 +000086VariableProxy::VariableProxy(Isolate* isolate,
87 Handle<String> name,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000088 bool is_this,
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000089 Interface* interface,
90 int position)
rossberg@chromium.org717967f2011-07-20 13:44:42 +000091 : Expression(isolate),
92 name_(name),
93 var_(NULL),
94 is_this_(is_this),
rossberg@chromium.org717967f2011-07-20 13:44:42 +000095 is_trivial_(false),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +000096 is_lvalue_(false),
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000097 position_(position),
98 interface_(interface) {
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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104void VariableProxy::BindTo(Variable* var) {
105 ASSERT(var_ == NULL); // must be bound only once
106 ASSERT(var != NULL); // must bind
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000107 ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
109 // Ideally CONST-ness should match. However, this is very hard to achieve
110 // because we don't know the exact semantics of conflicting (const and
111 // non-const) multiple variable declarations, const vars introduced via
112 // eval() etc. Const-ness and variable declarations are a complete mess
113 // in JS. Sigh...
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114 var_ = var;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000115 var->set_is_used(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000116}
117
118
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000119Assignment::Assignment(Isolate* isolate,
120 Token::Value op,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000121 Expression* target,
122 Expression* value,
123 int pos)
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000124 : Expression(isolate),
125 op_(op),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000126 target_(target),
127 value_(value),
128 pos_(pos),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000129 binary_operation_(NULL),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000130 assignment_id_(GetNextId(isolate)),
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +0000131 is_monomorphic_(false) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000132
133
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000134Token::Value Assignment::binary_op() const {
135 switch (op_) {
136 case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
137 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
138 case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
139 case Token::ASSIGN_SHL: return Token::SHL;
140 case Token::ASSIGN_SAR: return Token::SAR;
141 case Token::ASSIGN_SHR: return Token::SHR;
142 case Token::ASSIGN_ADD: return Token::ADD;
143 case Token::ASSIGN_SUB: return Token::SUB;
144 case Token::ASSIGN_MUL: return Token::MUL;
145 case Token::ASSIGN_DIV: return Token::DIV;
146 case Token::ASSIGN_MOD: return Token::MOD;
147 default: UNREACHABLE();
148 }
149 return Token::ILLEGAL;
150}
151
152
153bool FunctionLiteral::AllowsLazyCompilation() {
154 return scope()->AllowsLazyCompilation();
155}
156
157
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000158bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
159 return scope()->AllowsLazyCompilationWithoutContext();
160}
161
162
danno@chromium.orgc612e022011-11-10 11:38:15 +0000163int FunctionLiteral::start_position() const {
164 return scope()->start_position();
165}
166
167
168int FunctionLiteral::end_position() const {
169 return scope()->end_position();
170}
171
172
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000173LanguageMode FunctionLiteral::language_mode() const {
174 return scope()->language_mode();
danno@chromium.orgc612e022011-11-10 11:38:15 +0000175}
176
177
ulan@chromium.org812308e2012-02-29 15:58:45 +0000178ObjectLiteral::Property::Property(Literal* key,
179 Expression* value,
180 Isolate* isolate) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000181 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 key_ = key;
183 value_ = value;
184 Object* k = *key->handle();
ulan@chromium.org812308e2012-02-29 15:58:45 +0000185 if (k->IsSymbol() &&
186 isolate->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) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000199 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200 value_ = value;
201 kind_ = is_getter ? GETTER : SETTER;
202}
203
204
ager@chromium.org3811b432009-10-28 14:53:37 +0000205bool ObjectLiteral::Property::IsCompileTimeValue() {
206 return kind_ == CONSTANT ||
207 (kind_ == MATERIALIZED_LITERAL &&
208 CompileTimeValue::IsCompileTimeValue(value_));
209}
210
211
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000212void ObjectLiteral::Property::set_emit_store(bool emit_store) {
213 emit_store_ = emit_store;
214}
215
216
217bool ObjectLiteral::Property::emit_store() {
218 return emit_store_;
219}
220
221
222bool IsEqualString(void* first, void* second) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000223 ASSERT((*reinterpret_cast<String**>(first))->IsString());
224 ASSERT((*reinterpret_cast<String**>(second))->IsString());
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000225 Handle<String> h1(reinterpret_cast<String**>(first));
226 Handle<String> h2(reinterpret_cast<String**>(second));
227 return (*h1)->Equals(*h2);
228}
229
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000230
231bool IsEqualNumber(void* first, void* second) {
232 ASSERT((*reinterpret_cast<Object**>(first))->IsNumber());
233 ASSERT((*reinterpret_cast<Object**>(second))->IsNumber());
234
235 Handle<Object> h1(reinterpret_cast<Object**>(first));
236 Handle<Object> h2(reinterpret_cast<Object**>(second));
237 if (h1->IsSmi()) {
238 return h2->IsSmi() && *h1 == *h2;
239 }
240 if (h2->IsSmi()) return false;
241 Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1);
242 Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2);
243 ASSERT(isfinite(n1->value()));
244 ASSERT(isfinite(n2->value()));
245 return n1->value() == n2->value();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000246}
247
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000248
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000249void ObjectLiteral::CalculateEmitStore(Zone* zone) {
250 ZoneAllocationPolicy allocator(zone);
251
252 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity,
253 allocator);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000254 for (int i = properties()->length() - 1; i >= 0; i--) {
255 ObjectLiteral::Property* property = properties()->at(i);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000256 Literal* literal = property->key();
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000257 if (literal->handle()->IsNull()) continue;
258 uint32_t hash = literal->Hash();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000259 // If the key of a computed property is in the table, do not emit
260 // a store for the property later.
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000261 if (property->kind() == ObjectLiteral::Property::COMPUTED &&
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000262 table.Lookup(literal, hash, false, allocator) != NULL) {
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000263 property->set_emit_store(false);
264 } else {
265 // Add key to the table.
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000266 table.Lookup(literal, hash, true, allocator);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000267 }
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000268 }
269}
270
271
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000272void TargetCollector::AddTarget(Label* target, Zone* zone) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273 // Add the label to the collector, but discard duplicates.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000274 int length = targets_.length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275 for (int i = 0; i < length; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000276 if (targets_[i] == target) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000278 targets_.Add(target, zone);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279}
280
281
ricow@chromium.org65fae842010-08-25 15:26:24 +0000282bool UnaryOperation::ResultOverwriteAllowed() {
283 switch (op_) {
284 case Token::BIT_NOT:
285 case Token::SUB:
286 return true;
287 default:
288 return false;
289 }
290}
291
292
293bool BinaryOperation::ResultOverwriteAllowed() {
294 switch (op_) {
295 case Token::COMMA:
296 case Token::OR:
297 case Token::AND:
298 return false;
299 case Token::BIT_OR:
300 case Token::BIT_XOR:
301 case Token::BIT_AND:
302 case Token::SHL:
303 case Token::SAR:
304 case Token::SHR:
305 case Token::ADD:
306 case Token::SUB:
307 case Token::MUL:
308 case Token::DIV:
309 case Token::MOD:
310 return true;
311 default:
312 UNREACHABLE();
313 }
314 return false;
315}
316
317
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000318static bool IsTypeof(Expression* expr) {
319 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
320 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
321}
322
323
324// Check for the pattern: typeof <expression> equals <string literal>.
325static bool MatchLiteralCompareTypeof(Expression* left,
326 Token::Value op,
327 Expression* right,
328 Expression** expr,
329 Handle<String>* check) {
330 if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
331 *expr = left->AsUnaryOperation()->expression();
332 *check = Handle<String>::cast(right->AsLiteral()->handle());
333 return true;
334 }
335 return false;
336}
337
338
ager@chromium.org04921a82011-06-27 13:21:41 +0000339bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
340 Handle<String>* check) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000341 return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) ||
342 MatchLiteralCompareTypeof(right_, op_, left_, expr, check);
343}
ager@chromium.org04921a82011-06-27 13:21:41 +0000344
ager@chromium.org04921a82011-06-27 13:21:41 +0000345
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000346static bool IsVoidOfLiteral(Expression* expr) {
347 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
348 return maybe_unary != NULL &&
349 maybe_unary->op() == Token::VOID &&
350 maybe_unary->expression()->AsLiteral() != NULL;
351}
352
353
354// Check for the pattern: void <literal> equals <expression>
355static bool MatchLiteralCompareUndefined(Expression* left,
356 Token::Value op,
357 Expression* right,
358 Expression** expr) {
359 if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
360 *expr = right;
ager@chromium.org04921a82011-06-27 13:21:41 +0000361 return true;
362 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000363 return false;
364}
365
366
367bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000368 return MatchLiteralCompareUndefined(left_, op_, right_, expr) ||
369 MatchLiteralCompareUndefined(right_, op_, left_, expr);
370}
ager@chromium.org04921a82011-06-27 13:21:41 +0000371
ager@chromium.org04921a82011-06-27 13:21:41 +0000372
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000373// Check for the pattern: null equals <expression>
374static bool MatchLiteralCompareNull(Expression* left,
375 Token::Value op,
376 Expression* right,
377 Expression** expr) {
378 if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
379 *expr = right;
ager@chromium.org04921a82011-06-27 13:21:41 +0000380 return true;
381 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000382 return false;
383}
384
385
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000386bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
387 return MatchLiteralCompareNull(left_, op_, right_, expr) ||
388 MatchLiteralCompareNull(right_, op_, left_, expr);
389}
390
391
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000392// ----------------------------------------------------------------------------
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000393// Inlining support
394
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000395bool Declaration::IsInlineable() const {
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000396 return proxy()->var()->IsStackAllocated();
397}
398
ulan@chromium.org812308e2012-02-29 15:58:45 +0000399bool FunctionDeclaration::IsInlineable() const {
400 return false;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000401}
402
403
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000404// ----------------------------------------------------------------------------
405// Recording of type feedback
406
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000407void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
408 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000409 // Record type feedback from the oracle in the AST.
jkummerow@chromium.org531dfe82012-03-20 13:01:16 +0000410 is_uninitialized_ = oracle->LoadIsUninitialized(this);
411 if (is_uninitialized_) return;
412
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000413 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000414 receiver_types_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000415 if (key()->IsPropertyName()) {
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000416 ArrayLengthStub array_stub(Code::LOAD_IC);
417 FunctionPrototypeStub proto_stub(Code::LOAD_IC);
418 StringLengthStub string_stub(Code::LOAD_IC, false);
419 if (oracle->LoadIsStub(this, &array_stub)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000420 is_array_length_ = true;
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000421 } else if (oracle->LoadIsStub(this, &string_stub)) {
ager@chromium.org378b34e2011-01-28 08:04:38 +0000422 is_string_length_ = true;
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000423 } else if (oracle->LoadIsStub(this, &proto_stub)) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000424 is_function_prototype_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000425 } else {
426 Literal* lit_key = key()->AsLiteral();
427 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
428 Handle<String> name = Handle<String>::cast(lit_key->handle());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000429 oracle->LoadReceiverTypes(this, name, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000430 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000431 } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000432 is_string_access_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000433 } else if (is_monomorphic_) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000434 receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this),
435 zone);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000436 } else if (oracle->LoadIsPolymorphic(this)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000437 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000438 oracle->CollectKeyedReceiverTypes(PropertyFeedbackId(), &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000439 }
440}
441
442
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000443void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle,
444 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000445 Property* prop = target()->AsProperty();
446 ASSERT(prop != NULL);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000447 TypeFeedbackId id = AssignmentFeedbackId();
448 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(id);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000449 receiver_types_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000450 if (prop->key()->IsPropertyName()) {
451 Literal* lit_key = prop->key()->AsLiteral();
452 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
453 Handle<String> name = Handle<String>::cast(lit_key->handle());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000454 oracle->StoreReceiverTypes(this, name, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000455 } else if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000456 // Record receiver type for monomorphic keyed stores.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000457 receiver_types_.Add(oracle->StoreMonomorphicReceiverType(id), zone);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000458 } else if (oracle->StoreIsPolymorphic(id)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000459 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000460 oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000461 }
462}
463
464
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000465void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle,
466 Zone* zone) {
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000467 TypeFeedbackId id = CountStoreFeedbackId();
468 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(id);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000469 receiver_types_.Clear();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000470 if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000471 // Record receiver type for monomorphic keyed stores.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000472 receiver_types_.Add(
473 oracle->StoreMonomorphicReceiverType(id), zone);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000474 } else if (oracle->StoreIsPolymorphic(id)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000475 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000476 oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000477 }
478}
479
480
481void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
482 TypeInfo info = oracle->SwitchType(this);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000483 if (info.IsUninitialized()) info = TypeInfo::Unknown();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000484 if (info.IsSmi()) {
485 compare_type_ = SMI_ONLY;
erikcorry0ad885c2011-11-21 13:51:57 +0000486 } else if (info.IsSymbol()) {
487 compare_type_ = SYMBOL_ONLY;
488 } else if (info.IsNonSymbol()) {
489 compare_type_ = STRING_ONLY;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000490 } else if (info.IsNonPrimitive()) {
491 compare_type_ = OBJECT_ONLY;
492 } else {
493 ASSERT(compare_type_ == NONE);
494 }
495}
496
497
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000498bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000499 // If there is an interceptor, we can't compute the target for a direct call.
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000500 if (type->has_named_interceptor()) return false;
501
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000502 if (check_type_ == RECEIVER_MAP_CHECK) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000503 // For primitive checks the holder is set up to point to the corresponding
504 // prototype object, i.e. one step of the algorithm below has been already
505 // performed. For non-primitive checks we clear it to allow computing
506 // targets for polymorphic calls.
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000507 holder_ = Handle<JSObject>::null();
508 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000509 LookupResult lookup(type->GetIsolate());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000510 while (true) {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000511 type->LookupDescriptor(NULL, *name, &lookup);
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000512 if (lookup.IsFound()) {
513 switch (lookup.type()) {
514 case CONSTANT_FUNCTION:
515 // We surely know the target for a constant function.
516 target_ =
517 Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
518 return true;
519 case NORMAL:
520 case FIELD:
521 case CALLBACKS:
522 case HANDLER:
523 case INTERCEPTOR:
524 // We don't know the target.
525 return false;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000526 case TRANSITION:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000527 case NONEXISTENT:
528 UNREACHABLE();
529 break;
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000530 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000531 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000532 // If we reach the end of the prototype chain, we don't know the target.
533 if (!type->prototype()->IsJSObject()) return false;
534 // Go up the prototype chain, recording where we are currently.
535 holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000536 if (!holder_->HasFastProperties()) return false;
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000537 type = Handle<Map>(holder()->map());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000538 }
539}
540
541
542bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000543 LookupResult* lookup) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000544 target_ = Handle<JSFunction>::null();
545 cell_ = Handle<JSGlobalPropertyCell>::null();
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000546 ASSERT(lookup->IsFound() &&
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000547 lookup->type() == NORMAL &&
548 lookup->holder() == *global);
549 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
550 if (cell_->value()->IsJSFunction()) {
551 Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
552 // If the function is in new space we assume it's more likely to
553 // change and thus prefer the general IC code.
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000554 if (!HEAP->InNewSpace(*candidate)) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000555 target_ = candidate;
556 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000557 }
558 }
559 return false;
560}
561
562
danno@chromium.org40cb8782011-05-25 07:58:50 +0000563void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
564 CallKind call_kind) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000565 is_monomorphic_ = oracle->CallIsMonomorphic(this);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000566 Property* property = expression()->AsProperty();
567 if (property == NULL) {
568 // Function call. Specialize for monomorphic calls.
569 if (is_monomorphic_) target_ = oracle->GetCallTarget(this);
570 } else {
571 // Method call. Specialize for the receiver types seen at runtime.
572 Literal* key = property->key()->AsLiteral();
573 ASSERT(key != NULL && key->handle()->IsString());
574 Handle<String> name = Handle<String>::cast(key->handle());
575 receiver_types_.Clear();
576 oracle->CallReceiverTypes(this, name, call_kind, &receiver_types_);
577#ifdef DEBUG
578 if (FLAG_enable_slow_asserts) {
579 int length = receiver_types_.length();
580 for (int i = 0; i < length; i++) {
581 Handle<Map> map = receiver_types_.at(i);
582 ASSERT(!map.is_null() && *map != NULL);
583 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000584 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000585#endif
586 check_type_ = oracle->GetCallCheckType(this);
587 if (is_monomorphic_) {
588 Handle<Map> map;
589 if (receiver_types_.length() > 0) {
590 ASSERT(check_type_ == RECEIVER_MAP_CHECK);
591 map = receiver_types_.at(0);
592 } else {
593 ASSERT(check_type_ != RECEIVER_MAP_CHECK);
594 holder_ = Handle<JSObject>(
595 oracle->GetPrototypeForPrimitiveCheck(check_type_));
596 map = Handle<Map>(holder_->map());
597 }
598 is_monomorphic_ = ComputeTarget(map, name);
599 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000600 }
601}
602
603
ulan@chromium.org967e2702012-02-28 09:49:15 +0000604void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
605 is_monomorphic_ = oracle->CallNewIsMonomorphic(this);
606 if (is_monomorphic_) {
607 target_ = oracle->GetCallNewTarget(this);
608 }
609}
610
611
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000612void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
613 receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(this)
614 ? oracle->GetObjectLiteralStoreMap(this)
615 : Handle<Map>::null();
616}
617
618
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000619// ----------------------------------------------------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000620// Implementation of AstVisitor
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000622void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
623 for (int i = 0; i < declarations->length(); i++) {
624 Visit(declarations->at(i));
625 }
626}
627
628
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000629void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630 for (int i = 0; i < statements->length(); i++) {
631 Visit(statements->at(i));
632 }
633}
634
635
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000636void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000637 for (int i = 0; i < expressions->length(); i++) {
638 // The variable statement visiting code may pass NULL expressions
639 // to this code. Maybe this should be handled by introducing an
640 // undefined expression or literal? Revisit this code if this
641 // changes
642 Expression* expression = expressions->at(i);
643 if (expression != NULL) Visit(expression);
644 }
645}
646
647
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000648// ----------------------------------------------------------------------------
649// Regular expressions
650
651#define MAKE_ACCEPT(Name) \
652 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
653 return visitor->Visit##Name(this, data); \
654 }
655FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
656#undef MAKE_ACCEPT
657
658#define MAKE_TYPE_CASE(Name) \
659 RegExp##Name* RegExpTree::As##Name() { \
660 return NULL; \
661 } \
662 bool RegExpTree::Is##Name() { return false; }
663FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
664#undef MAKE_TYPE_CASE
665
666#define MAKE_TYPE_CASE(Name) \
667 RegExp##Name* RegExp##Name::As##Name() { \
668 return this; \
669 } \
670 bool RegExp##Name::Is##Name() { return true; }
671FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
672#undef MAKE_TYPE_CASE
673
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000674
ager@chromium.org32912102009-01-16 10:38:43 +0000675static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
676 Interval result = Interval::Empty();
677 for (int i = 0; i < children->length(); i++)
678 result = result.Union(children->at(i)->CaptureRegisters());
679 return result;
680}
681
682
683Interval RegExpAlternative::CaptureRegisters() {
684 return ListCaptureRegisters(nodes());
685}
686
687
688Interval RegExpDisjunction::CaptureRegisters() {
689 return ListCaptureRegisters(alternatives());
690}
691
692
693Interval RegExpLookahead::CaptureRegisters() {
694 return body()->CaptureRegisters();
695}
696
697
698Interval RegExpCapture::CaptureRegisters() {
699 Interval self(StartRegister(index()), EndRegister(index()));
700 return self.Union(body()->CaptureRegisters());
701}
702
703
704Interval RegExpQuantifier::CaptureRegisters() {
705 return body()->CaptureRegisters();
706}
707
708
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000709bool RegExpAssertion::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000710 return type() == RegExpAssertion::START_OF_INPUT;
711}
712
713
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000714bool RegExpAssertion::IsAnchoredAtEnd() {
715 return type() == RegExpAssertion::END_OF_INPUT;
716}
717
718
719bool RegExpAlternative::IsAnchoredAtStart() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000720 ZoneList<RegExpTree*>* nodes = this->nodes();
721 for (int i = 0; i < nodes->length(); i++) {
722 RegExpTree* node = nodes->at(i);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000723 if (node->IsAnchoredAtStart()) { return true; }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000724 if (node->max_match() > 0) { return false; }
725 }
726 return false;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000727}
728
729
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000730bool RegExpAlternative::IsAnchoredAtEnd() {
731 ZoneList<RegExpTree*>* nodes = this->nodes();
732 for (int i = nodes->length() - 1; i >= 0; i--) {
733 RegExpTree* node = nodes->at(i);
734 if (node->IsAnchoredAtEnd()) { return true; }
735 if (node->max_match() > 0) { return false; }
736 }
737 return false;
738}
739
740
741bool RegExpDisjunction::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000742 ZoneList<RegExpTree*>* alternatives = this->alternatives();
743 for (int i = 0; i < alternatives->length(); i++) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000744 if (!alternatives->at(i)->IsAnchoredAtStart())
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000745 return false;
746 }
747 return true;
748}
749
750
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000751bool RegExpDisjunction::IsAnchoredAtEnd() {
752 ZoneList<RegExpTree*>* alternatives = this->alternatives();
753 for (int i = 0; i < alternatives->length(); i++) {
754 if (!alternatives->at(i)->IsAnchoredAtEnd())
755 return false;
756 }
757 return true;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000758}
759
760
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000761bool RegExpLookahead::IsAnchoredAtStart() {
762 return is_positive() && body()->IsAnchoredAtStart();
763}
764
765
766bool RegExpCapture::IsAnchoredAtStart() {
767 return body()->IsAnchoredAtStart();
768}
769
770
771bool RegExpCapture::IsAnchoredAtEnd() {
772 return body()->IsAnchoredAtEnd();
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000773}
774
775
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000776// Convert regular expression trees to a simple sexp representation.
777// This representation should be different from the input grammar
778// in as many cases as possible, to make it more difficult for incorrect
779// parses to look as correct ones which is likely if the input and
780// output formats are alike.
781class RegExpUnparser: public RegExpVisitor {
782 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000783 explicit RegExpUnparser(Zone* zone);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000784 void VisitCharacterRange(CharacterRange that);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000785 SmartArrayPointer<const char> ToString() { return stream_.ToCString(); }
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000786#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
787 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
788#undef MAKE_CASE
789 private:
790 StringStream* stream() { return &stream_; }
791 HeapStringAllocator alloc_;
792 StringStream stream_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000793 Zone* zone_;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000794};
795
796
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000797RegExpUnparser::RegExpUnparser(Zone* zone) : stream_(&alloc_), zone_(zone) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000798}
799
800
801void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
802 stream()->Add("(|");
803 for (int i = 0; i < that->alternatives()->length(); i++) {
804 stream()->Add(" ");
805 that->alternatives()->at(i)->Accept(this, data);
806 }
807 stream()->Add(")");
808 return NULL;
809}
810
811
812void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
813 stream()->Add("(:");
814 for (int i = 0; i < that->nodes()->length(); i++) {
815 stream()->Add(" ");
816 that->nodes()->at(i)->Accept(this, data);
817 }
818 stream()->Add(")");
819 return NULL;
820}
821
822
823void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
824 stream()->Add("%k", that.from());
825 if (!that.IsSingleton()) {
826 stream()->Add("-%k", that.to());
827 }
828}
829
830
831
832void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
833 void* data) {
834 if (that->is_negated())
835 stream()->Add("^");
836 stream()->Add("[");
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000837 for (int i = 0; i < that->ranges(zone_)->length(); i++) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000838 if (i > 0) stream()->Add(" ");
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000839 VisitCharacterRange(that->ranges(zone_)->at(i));
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000840 }
841 stream()->Add("]");
842 return NULL;
843}
844
845
846void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
847 switch (that->type()) {
848 case RegExpAssertion::START_OF_INPUT:
849 stream()->Add("@^i");
850 break;
851 case RegExpAssertion::END_OF_INPUT:
852 stream()->Add("@$i");
853 break;
854 case RegExpAssertion::START_OF_LINE:
855 stream()->Add("@^l");
856 break;
857 case RegExpAssertion::END_OF_LINE:
858 stream()->Add("@$l");
859 break;
860 case RegExpAssertion::BOUNDARY:
861 stream()->Add("@b");
862 break;
863 case RegExpAssertion::NON_BOUNDARY:
864 stream()->Add("@B");
865 break;
866 }
867 return NULL;
868}
869
870
871void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
872 stream()->Add("'");
873 Vector<const uc16> chardata = that->data();
874 for (int i = 0; i < chardata.length(); i++) {
875 stream()->Add("%k", chardata[i]);
876 }
877 stream()->Add("'");
878 return NULL;
879}
880
881
882void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
883 if (that->elements()->length() == 1) {
884 that->elements()->at(0).data.u_atom->Accept(this, data);
885 } else {
886 stream()->Add("(!");
887 for (int i = 0; i < that->elements()->length(); i++) {
888 stream()->Add(" ");
889 that->elements()->at(i).data.u_atom->Accept(this, data);
890 }
891 stream()->Add(")");
892 }
893 return NULL;
894}
895
896
897void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
898 stream()->Add("(# %i ", that->min());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000899 if (that->max() == RegExpTree::kInfinity) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000900 stream()->Add("- ");
901 } else {
902 stream()->Add("%i ", that->max());
903 }
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000904 stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000905 that->body()->Accept(this, data);
906 stream()->Add(")");
907 return NULL;
908}
909
910
911void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
912 stream()->Add("(^ ");
913 that->body()->Accept(this, data);
914 stream()->Add(")");
915 return NULL;
916}
917
918
919void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
920 stream()->Add("(-> ");
921 stream()->Add(that->is_positive() ? "+ " : "- ");
922 that->body()->Accept(this, data);
923 stream()->Add(")");
924 return NULL;
925}
926
927
928void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
929 void* data) {
930 stream()->Add("(<- %i)", that->index());
931 return NULL;
932}
933
934
935void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
936 stream()->Put('%');
937 return NULL;
938}
939
940
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000941SmartArrayPointer<const char> RegExpTree::ToString(Zone* zone) {
942 RegExpUnparser unparser(zone);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000943 Accept(&unparser, NULL);
944 return unparser.ToString();
945}
946
947
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000948RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
949 : alternatives_(alternatives) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000950 ASSERT(alternatives->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000951 RegExpTree* first_alternative = alternatives->at(0);
952 min_match_ = first_alternative->min_match();
953 max_match_ = first_alternative->max_match();
954 for (int i = 1; i < alternatives->length(); i++) {
955 RegExpTree* alternative = alternatives->at(i);
956 min_match_ = Min(min_match_, alternative->min_match());
957 max_match_ = Max(max_match_, alternative->max_match());
958 }
959}
960
961
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000962static int IncreaseBy(int previous, int increase) {
963 if (RegExpTree::kInfinity - previous < increase) {
964 return RegExpTree::kInfinity;
965 } else {
966 return previous + increase;
967 }
968}
969
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000970RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
971 : nodes_(nodes) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000972 ASSERT(nodes->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000973 min_match_ = 0;
974 max_match_ = 0;
975 for (int i = 0; i < nodes->length(); i++) {
976 RegExpTree* node = nodes->at(i);
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000977 int node_min_match = node->min_match();
978 min_match_ = IncreaseBy(min_match_, node_min_match);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000979 int node_max_match = node->max_match();
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000980 max_match_ = IncreaseBy(max_match_, node_max_match);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000981 }
982}
983
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000984
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000985CaseClause::CaseClause(Isolate* isolate,
986 Expression* label,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000987 ZoneList<Statement*>* statements,
988 int pos)
989 : label_(label),
990 statements_(statements),
991 position_(pos),
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000992 compare_type_(NONE),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000993 compare_id_(AstNode::GetNextId(isolate)),
994 entry_id_(AstNode::GetNextId(isolate)) {
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000995}
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000996
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +0000997
erik.corry@gmail.comed49e962012-04-17 11:57:53 +0000998#define REGULAR_NODE(NodeType) \
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +0000999 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1000 increase_node_count(); \
1001 }
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001002#define DONT_OPTIMIZE_NODE(NodeType) \
1003 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1004 increase_node_count(); \
1005 add_flag(kDontOptimize); \
1006 add_flag(kDontInline); \
1007 add_flag(kDontSelfOptimize); \
1008 }
1009#define DONT_INLINE_NODE(NodeType) \
1010 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1011 increase_node_count(); \
1012 add_flag(kDontInline); \
1013 }
1014#define DONT_SELFOPTIMIZE_NODE(NodeType) \
1015 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1016 increase_node_count(); \
1017 add_flag(kDontSelfOptimize); \
1018 }
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001019#define DONT_CACHE_NODE(NodeType) \
1020 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1021 increase_node_count(); \
1022 add_flag(kDontOptimize); \
1023 add_flag(kDontInline); \
1024 add_flag(kDontSelfOptimize); \
1025 add_flag(kDontCache); \
1026 }
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001027
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001028REGULAR_NODE(VariableDeclaration)
1029REGULAR_NODE(FunctionDeclaration)
1030REGULAR_NODE(Block)
1031REGULAR_NODE(ExpressionStatement)
1032REGULAR_NODE(EmptyStatement)
1033REGULAR_NODE(IfStatement)
1034REGULAR_NODE(ContinueStatement)
1035REGULAR_NODE(BreakStatement)
1036REGULAR_NODE(ReturnStatement)
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00001037REGULAR_NODE(SwitchStatement)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001038REGULAR_NODE(Conditional)
1039REGULAR_NODE(Literal)
1040REGULAR_NODE(ObjectLiteral)
yangguo@chromium.org9c741c82012-06-28 15:04:22 +00001041REGULAR_NODE(RegExpLiteral)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001042REGULAR_NODE(Assignment)
1043REGULAR_NODE(Throw)
1044REGULAR_NODE(Property)
1045REGULAR_NODE(UnaryOperation)
1046REGULAR_NODE(CountOperation)
1047REGULAR_NODE(BinaryOperation)
1048REGULAR_NODE(CompareOperation)
1049REGULAR_NODE(ThisFunction)
1050REGULAR_NODE(Call)
1051REGULAR_NODE(CallNew)
1052// In theory, for VariableProxy we'd have to add:
1053// if (node->var()->IsLookupSlot()) add_flag(kDontInline);
1054// But node->var() is usually not bound yet at VariableProxy creation time, and
1055// LOOKUP variables only result from constructs that cannot be inlined anyway.
1056REGULAR_NODE(VariableProxy)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001057
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001058// We currently do not optimize any modules.
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001059DONT_OPTIMIZE_NODE(ModuleDeclaration)
1060DONT_OPTIMIZE_NODE(ImportDeclaration)
1061DONT_OPTIMIZE_NODE(ExportDeclaration)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001062DONT_OPTIMIZE_NODE(ModuleVariable)
1063DONT_OPTIMIZE_NODE(ModulePath)
1064DONT_OPTIMIZE_NODE(ModuleUrl)
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001065DONT_OPTIMIZE_NODE(ModuleStatement)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001066DONT_OPTIMIZE_NODE(WithStatement)
1067DONT_OPTIMIZE_NODE(TryCatchStatement)
1068DONT_OPTIMIZE_NODE(TryFinallyStatement)
1069DONT_OPTIMIZE_NODE(DebuggerStatement)
1070DONT_OPTIMIZE_NODE(SharedFunctionInfoLiteral)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001071
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001072DONT_INLINE_NODE(ArrayLiteral) // TODO(1322): Allow materialized literals.
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001073DONT_INLINE_NODE(FunctionLiteral)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001074
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001075DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
1076DONT_SELFOPTIMIZE_NODE(WhileStatement)
1077DONT_SELFOPTIMIZE_NODE(ForStatement)
1078DONT_SELFOPTIMIZE_NODE(ForInStatement)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001079
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001080DONT_CACHE_NODE(ModuleLiteral)
1081
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001082void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
1083 increase_node_count();
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001084 if (node->is_jsruntime()) {
1085 // Don't try to inline JS runtime calls because we don't (currently) even
1086 // optimize them.
1087 add_flag(kDontInline);
1088 } else if (node->function()->intrinsic_type == Runtime::INLINE &&
jkummerow@chromium.org59297c72013-01-09 16:32:23 +00001089 (node->name()->IsOneByteEqualTo(
1090 STATIC_ASCII_VECTOR("_ArgumentsLength")) ||
1091 node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001092 // Don't inline the %_ArgumentsLength or %_Arguments because their
1093 // implementation will not work. There is no stack frame to get them
1094 // from.
1095 add_flag(kDontInline);
1096 }
1097}
1098
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001099#undef REGULAR_NODE
1100#undef DONT_OPTIMIZE_NODE
1101#undef DONT_INLINE_NODE
1102#undef DONT_SELFOPTIMIZE_NODE
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001103#undef DONT_CACHE_NODE
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001104
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001105
1106Handle<String> Literal::ToString() {
1107 if (handle_->IsString()) return Handle<String>::cast(handle_);
1108 ASSERT(handle_->IsNumber());
1109 char arr[100];
1110 Vector<char> buffer(arr, ARRAY_SIZE(arr));
1111 const char* str;
1112 if (handle_->IsSmi()) {
1113 // Optimization only, the heap number case would subsume this.
1114 OS::SNPrintF(buffer, "%d", Smi::cast(*handle_)->value());
1115 str = arr;
1116 } else {
1117 str = DoubleToCString(handle_->Number(), buffer);
1118 }
1119 return FACTORY->NewStringFromAscii(CStrVector(str));
1120}
1121
1122
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123} } // namespace v8::internal