blob: adbad418a5b8199c298fcfe2a07c3491da314845 [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"
32#include "conversions.h"
33#include "hashmap.h"
ager@chromium.org3811b432009-10-28 14:53:37 +000034#include "parser.h"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000035#include "property-details.h"
36#include "property.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037#include "scopes.h"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000038#include "string-stream.h"
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000039#include "type-info.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000040
kasperl@chromium.org71affb52009-05-26 05:44:31 +000041namespace v8 {
42namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044// ----------------------------------------------------------------------------
45// All the Accept member functions for each syntax tree node type.
46
lrn@chromium.org25156de2010-04-06 13:10:27 +000047#define DECL_ACCEPT(type) \
48 void type::Accept(AstVisitor* v) { v->Visit##type(this); }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000049AST_NODE_LIST(DECL_ACCEPT)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050#undef DECL_ACCEPT
51
52
53// ----------------------------------------------------------------------------
54// Implementation of other node functionality.
55
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000056
57bool Expression::IsSmiLiteral() {
58 return AsLiteral() != NULL && AsLiteral()->handle()->IsSmi();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000059}
60
61
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000062bool Expression::IsStringLiteral() {
63 return AsLiteral() != NULL && AsLiteral()->handle()->IsString();
64}
65
66
67bool Expression::IsNullLiteral() {
68 return AsLiteral() != NULL && AsLiteral()->handle()->IsNull();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000069}
70
71
rossberg@chromium.org717967f2011-07-20 13:44:42 +000072VariableProxy::VariableProxy(Isolate* isolate, Variable* var)
73 : Expression(isolate),
74 name_(var->name()),
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000075 var_(NULL), // Will be set by the call to BindTo.
76 is_this_(var->is_this()),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000077 is_trivial_(false),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +000078 is_lvalue_(false),
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000079 position_(RelocInfo::kNoPosition),
80 interface_(var->interface()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000081 BindTo(var);
82}
83
84
rossberg@chromium.org717967f2011-07-20 13:44:42 +000085VariableProxy::VariableProxy(Isolate* isolate,
86 Handle<String> name,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000087 bool is_this,
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000088 Interface* interface,
89 int position)
rossberg@chromium.org717967f2011-07-20 13:44:42 +000090 : Expression(isolate),
91 name_(name),
92 var_(NULL),
93 is_this_(is_this),
rossberg@chromium.org717967f2011-07-20 13:44:42 +000094 is_trivial_(false),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +000095 is_lvalue_(false),
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000096 position_(position),
97 interface_(interface) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000098 // Names must be canonicalized for fast equality checks.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000099 ASSERT(name->IsSymbol());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000100}
101
102
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103void VariableProxy::BindTo(Variable* var) {
104 ASSERT(var_ == NULL); // must be bound only once
105 ASSERT(var != NULL); // must bind
106 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
107 // Ideally CONST-ness should match. However, this is very hard to achieve
108 // because we don't know the exact semantics of conflicting (const and
109 // non-const) multiple variable declarations, const vars introduced via
110 // eval() etc. Const-ness and variable declarations are a complete mess
111 // in JS. Sigh...
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112 var_ = var;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000113 var->set_is_used(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114}
115
116
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000117Assignment::Assignment(Isolate* isolate,
118 Token::Value op,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000119 Expression* target,
120 Expression* value,
121 int pos)
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000122 : Expression(isolate),
123 op_(op),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124 target_(target),
125 value_(value),
126 pos_(pos),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000127 binary_operation_(NULL),
128 compound_load_id_(kNoNumber),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000129 assignment_id_(GetNextId(isolate)),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000130 block_start_(false),
131 block_end_(false),
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +0000132 is_monomorphic_(false) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000133
134
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135Token::Value Assignment::binary_op() const {
136 switch (op_) {
137 case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
138 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
139 case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
140 case Token::ASSIGN_SHL: return Token::SHL;
141 case Token::ASSIGN_SAR: return Token::SAR;
142 case Token::ASSIGN_SHR: return Token::SHR;
143 case Token::ASSIGN_ADD: return Token::ADD;
144 case Token::ASSIGN_SUB: return Token::SUB;
145 case Token::ASSIGN_MUL: return Token::MUL;
146 case Token::ASSIGN_DIV: return Token::DIV;
147 case Token::ASSIGN_MOD: return Token::MOD;
148 default: UNREACHABLE();
149 }
150 return Token::ILLEGAL;
151}
152
153
154bool FunctionLiteral::AllowsLazyCompilation() {
155 return scope()->AllowsLazyCompilation();
156}
157
158
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000159bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
160 return scope()->AllowsLazyCompilationWithoutContext();
161}
162
163
danno@chromium.orgc612e022011-11-10 11:38:15 +0000164int FunctionLiteral::start_position() const {
165 return scope()->start_position();
166}
167
168
169int FunctionLiteral::end_position() const {
170 return scope()->end_position();
171}
172
173
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000174LanguageMode FunctionLiteral::language_mode() const {
175 return scope()->language_mode();
danno@chromium.orgc612e022011-11-10 11:38:15 +0000176}
177
178
ulan@chromium.org812308e2012-02-29 15:58:45 +0000179ObjectLiteral::Property::Property(Literal* key,
180 Expression* value,
181 Isolate* isolate) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000182 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183 key_ = key;
184 value_ = value;
185 Object* k = *key->handle();
ulan@chromium.org812308e2012-02-29 15:58:45 +0000186 if (k->IsSymbol() &&
187 isolate->heap()->Proto_symbol()->Equals(String::cast(k))) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 kind_ = PROTOTYPE;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000189 } else if (value_->AsMaterializedLiteral() != NULL) {
190 kind_ = MATERIALIZED_LITERAL;
191 } else if (value_->AsLiteral() != NULL) {
192 kind_ = CONSTANT;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193 } else {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000194 kind_ = COMPUTED;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195 }
196}
197
198
199ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000200 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201 value_ = value;
202 kind_ = is_getter ? GETTER : SETTER;
203}
204
205
ager@chromium.org3811b432009-10-28 14:53:37 +0000206bool ObjectLiteral::Property::IsCompileTimeValue() {
207 return kind_ == CONSTANT ||
208 (kind_ == MATERIALIZED_LITERAL &&
209 CompileTimeValue::IsCompileTimeValue(value_));
210}
211
212
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000213void ObjectLiteral::Property::set_emit_store(bool emit_store) {
214 emit_store_ = emit_store;
215}
216
217
218bool ObjectLiteral::Property::emit_store() {
219 return emit_store_;
220}
221
222
223bool IsEqualString(void* first, void* second) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000224 ASSERT((*reinterpret_cast<String**>(first))->IsString());
225 ASSERT((*reinterpret_cast<String**>(second))->IsString());
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000226 Handle<String> h1(reinterpret_cast<String**>(first));
227 Handle<String> h2(reinterpret_cast<String**>(second));
228 return (*h1)->Equals(*h2);
229}
230
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000231
232bool IsEqualNumber(void* first, void* second) {
233 ASSERT((*reinterpret_cast<Object**>(first))->IsNumber());
234 ASSERT((*reinterpret_cast<Object**>(second))->IsNumber());
235
236 Handle<Object> h1(reinterpret_cast<Object**>(first));
237 Handle<Object> h2(reinterpret_cast<Object**>(second));
238 if (h1->IsSmi()) {
239 return h2->IsSmi() && *h1 == *h2;
240 }
241 if (h2->IsSmi()) return false;
242 Handle<HeapNumber> n1 = Handle<HeapNumber>::cast(h1);
243 Handle<HeapNumber> n2 = Handle<HeapNumber>::cast(h2);
244 ASSERT(isfinite(n1->value()));
245 ASSERT(isfinite(n2->value()));
246 return n1->value() == n2->value();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000247}
248
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000249
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000250void ObjectLiteral::CalculateEmitStore(Zone* zone) {
251 ZoneAllocationPolicy allocator(zone);
252
253 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity,
254 allocator);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000255 for (int i = properties()->length() - 1; i >= 0; i--) {
256 ObjectLiteral::Property* property = properties()->at(i);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000257 Literal* literal = property->key();
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000258 if (literal->handle()->IsNull()) continue;
259 uint32_t hash = literal->Hash();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000260 // If the key of a computed property is in the table, do not emit
261 // a store for the property later.
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000262 if (property->kind() == ObjectLiteral::Property::COMPUTED &&
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000263 table.Lookup(literal, hash, false, allocator) != NULL) {
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000264 property->set_emit_store(false);
265 } else {
266 // Add key to the table.
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000267 table.Lookup(literal, hash, true, allocator);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000268 }
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000269 }
270}
271
272
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000273void TargetCollector::AddTarget(Label* target, Zone* zone) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000274 // Add the label to the collector, but discard duplicates.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000275 int length = targets_.length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000276 for (int i = 0; i < length; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000277 if (targets_[i] == target) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000278 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000279 targets_.Add(target, zone);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000280}
281
282
ricow@chromium.org65fae842010-08-25 15:26:24 +0000283bool UnaryOperation::ResultOverwriteAllowed() {
284 switch (op_) {
285 case Token::BIT_NOT:
286 case Token::SUB:
287 return true;
288 default:
289 return false;
290 }
291}
292
293
294bool BinaryOperation::ResultOverwriteAllowed() {
295 switch (op_) {
296 case Token::COMMA:
297 case Token::OR:
298 case Token::AND:
299 return false;
300 case Token::BIT_OR:
301 case Token::BIT_XOR:
302 case Token::BIT_AND:
303 case Token::SHL:
304 case Token::SAR:
305 case Token::SHR:
306 case Token::ADD:
307 case Token::SUB:
308 case Token::MUL:
309 case Token::DIV:
310 case Token::MOD:
311 return true;
312 default:
313 UNREACHABLE();
314 }
315 return false;
316}
317
318
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000319static bool IsTypeof(Expression* expr) {
320 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
321 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
322}
323
324
325// Check for the pattern: typeof <expression> equals <string literal>.
326static bool MatchLiteralCompareTypeof(Expression* left,
327 Token::Value op,
328 Expression* right,
329 Expression** expr,
330 Handle<String>* check) {
331 if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
332 *expr = left->AsUnaryOperation()->expression();
333 *check = Handle<String>::cast(right->AsLiteral()->handle());
334 return true;
335 }
336 return false;
337}
338
339
ager@chromium.org04921a82011-06-27 13:21:41 +0000340bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
341 Handle<String>* check) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000342 return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) ||
343 MatchLiteralCompareTypeof(right_, op_, left_, expr, check);
344}
ager@chromium.org04921a82011-06-27 13:21:41 +0000345
ager@chromium.org04921a82011-06-27 13:21:41 +0000346
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000347static bool IsVoidOfLiteral(Expression* expr) {
348 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
349 return maybe_unary != NULL &&
350 maybe_unary->op() == Token::VOID &&
351 maybe_unary->expression()->AsLiteral() != NULL;
352}
353
354
355// Check for the pattern: void <literal> equals <expression>
356static bool MatchLiteralCompareUndefined(Expression* left,
357 Token::Value op,
358 Expression* right,
359 Expression** expr) {
360 if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
361 *expr = right;
ager@chromium.org04921a82011-06-27 13:21:41 +0000362 return true;
363 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000364 return false;
365}
366
367
368bool CompareOperation::IsLiteralCompareUndefined(Expression** expr) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000369 return MatchLiteralCompareUndefined(left_, op_, right_, expr) ||
370 MatchLiteralCompareUndefined(right_, op_, left_, expr);
371}
ager@chromium.org04921a82011-06-27 13:21:41 +0000372
ager@chromium.org04921a82011-06-27 13:21:41 +0000373
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000374// Check for the pattern: null equals <expression>
375static bool MatchLiteralCompareNull(Expression* left,
376 Token::Value op,
377 Expression* right,
378 Expression** expr) {
379 if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
380 *expr = right;
ager@chromium.org04921a82011-06-27 13:21:41 +0000381 return true;
382 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000383 return false;
384}
385
386
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000387bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
388 return MatchLiteralCompareNull(left_, op_, right_, expr) ||
389 MatchLiteralCompareNull(right_, op_, left_, expr);
390}
391
392
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393// ----------------------------------------------------------------------------
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000394// Inlining support
395
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000396bool Declaration::IsInlineable() const {
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000397 return proxy()->var()->IsStackAllocated();
398}
399
ulan@chromium.org812308e2012-02-29 15:58:45 +0000400bool FunctionDeclaration::IsInlineable() const {
401 return false;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000402}
403
404
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000405// ----------------------------------------------------------------------------
406// Recording of type feedback
407
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000408void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
409 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000410 // Record type feedback from the oracle in the AST.
jkummerow@chromium.org531dfe82012-03-20 13:01:16 +0000411 is_uninitialized_ = oracle->LoadIsUninitialized(this);
412 if (is_uninitialized_) return;
413
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000414 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000415 receiver_types_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000416 if (key()->IsPropertyName()) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000417 if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000418 is_array_length_ = true;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000419 } else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) {
ager@chromium.org378b34e2011-01-28 08:04:38 +0000420 is_string_length_ = true;
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000421 } else if (oracle->LoadIsBuiltin(this,
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000422 Builtins::kLoadIC_FunctionPrototype)) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000423 is_function_prototype_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000424 } else {
425 Literal* lit_key = key()->AsLiteral();
426 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
427 Handle<String> name = Handle<String>::cast(lit_key->handle());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000428 oracle->LoadReceiverTypes(this, name, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000429 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000430 } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000431 is_string_access_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000432 } else if (is_monomorphic_) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000433 receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this),
434 zone);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000435 } else if (oracle->LoadIsMegamorphicWithTypeInfo(this)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000436 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000437 oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000438 }
439}
440
441
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000442void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle,
443 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000444 Property* prop = target()->AsProperty();
445 ASSERT(prop != NULL);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000446 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000447 receiver_types_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000448 if (prop->key()->IsPropertyName()) {
449 Literal* lit_key = prop->key()->AsLiteral();
450 ASSERT(lit_key != NULL && lit_key->handle()->IsString());
451 Handle<String> name = Handle<String>::cast(lit_key->handle());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000452 oracle->StoreReceiverTypes(this, name, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000453 } else if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000454 // Record receiver type for monomorphic keyed stores.
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000455 receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this), zone);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000456 } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000457 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000458 oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000459 }
460}
461
462
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000463void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle,
464 Zone* zone) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000465 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000466 receiver_types_.Clear();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000467 if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000468 // Record receiver type for monomorphic keyed stores.
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000469 receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this), zone);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000470 } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000471 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000472 oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000473 }
474}
475
476
477void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
478 TypeInfo info = oracle->SwitchType(this);
479 if (info.IsSmi()) {
480 compare_type_ = SMI_ONLY;
erikcorry0ad885c2011-11-21 13:51:57 +0000481 } else if (info.IsSymbol()) {
482 compare_type_ = SYMBOL_ONLY;
483 } else if (info.IsNonSymbol()) {
484 compare_type_ = STRING_ONLY;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000485 } else if (info.IsNonPrimitive()) {
486 compare_type_ = OBJECT_ONLY;
487 } else {
488 ASSERT(compare_type_ == NONE);
489 }
490}
491
492
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000493bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000494 // If there is an interceptor, we can't compute the target for a direct call.
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000495 if (type->has_named_interceptor()) return false;
496
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000497 if (check_type_ == RECEIVER_MAP_CHECK) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000498 // For primitive checks the holder is set up to point to the corresponding
499 // prototype object, i.e. one step of the algorithm below has been already
500 // performed. For non-primitive checks we clear it to allow computing
501 // targets for polymorphic calls.
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000502 holder_ = Handle<JSObject>::null();
503 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000504 LookupResult lookup(type->GetIsolate());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000505 while (true) {
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000506 type->LookupDescriptor(NULL, *name, &lookup);
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000507 if (lookup.IsFound()) {
508 switch (lookup.type()) {
509 case CONSTANT_FUNCTION:
510 // We surely know the target for a constant function.
511 target_ =
512 Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
513 return true;
514 case NORMAL:
515 case FIELD:
516 case CALLBACKS:
517 case HANDLER:
518 case INTERCEPTOR:
519 // We don't know the target.
520 return false;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000521 case TRANSITION:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000522 case NONEXISTENT:
523 UNREACHABLE();
524 break;
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000525 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000526 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000527 // If we reach the end of the prototype chain, we don't know the target.
528 if (!type->prototype()->IsJSObject()) return false;
529 // Go up the prototype chain, recording where we are currently.
530 holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
rossberg@chromium.org657d53b2012-07-12 11:06:03 +0000531 if (!holder_->HasFastProperties()) return false;
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000532 type = Handle<Map>(holder()->map());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000533 }
534}
535
536
537bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000538 LookupResult* lookup) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000539 target_ = Handle<JSFunction>::null();
540 cell_ = Handle<JSGlobalPropertyCell>::null();
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000541 ASSERT(lookup->IsFound() &&
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000542 lookup->type() == NORMAL &&
543 lookup->holder() == *global);
544 cell_ = Handle<JSGlobalPropertyCell>(global->GetPropertyCell(lookup));
545 if (cell_->value()->IsJSFunction()) {
546 Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
547 // If the function is in new space we assume it's more likely to
548 // change and thus prefer the general IC code.
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000549 if (!HEAP->InNewSpace(*candidate)) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000550 target_ = candidate;
551 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000552 }
553 }
554 return false;
555}
556
557
danno@chromium.org40cb8782011-05-25 07:58:50 +0000558void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
559 CallKind call_kind) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000560 is_monomorphic_ = oracle->CallIsMonomorphic(this);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000561 Property* property = expression()->AsProperty();
562 if (property == NULL) {
563 // Function call. Specialize for monomorphic calls.
564 if (is_monomorphic_) target_ = oracle->GetCallTarget(this);
565 } else {
566 // Method call. Specialize for the receiver types seen at runtime.
567 Literal* key = property->key()->AsLiteral();
568 ASSERT(key != NULL && key->handle()->IsString());
569 Handle<String> name = Handle<String>::cast(key->handle());
570 receiver_types_.Clear();
571 oracle->CallReceiverTypes(this, name, call_kind, &receiver_types_);
572#ifdef DEBUG
573 if (FLAG_enable_slow_asserts) {
574 int length = receiver_types_.length();
575 for (int i = 0; i < length; i++) {
576 Handle<Map> map = receiver_types_.at(i);
577 ASSERT(!map.is_null() && *map != NULL);
578 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000579 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000580#endif
581 check_type_ = oracle->GetCallCheckType(this);
582 if (is_monomorphic_) {
583 Handle<Map> map;
584 if (receiver_types_.length() > 0) {
585 ASSERT(check_type_ == RECEIVER_MAP_CHECK);
586 map = receiver_types_.at(0);
587 } else {
588 ASSERT(check_type_ != RECEIVER_MAP_CHECK);
589 holder_ = Handle<JSObject>(
590 oracle->GetPrototypeForPrimitiveCheck(check_type_));
591 map = Handle<Map>(holder_->map());
592 }
593 is_monomorphic_ = ComputeTarget(map, name);
594 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000595 }
596}
597
598
ulan@chromium.org967e2702012-02-28 09:49:15 +0000599void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
600 is_monomorphic_ = oracle->CallNewIsMonomorphic(this);
601 if (is_monomorphic_) {
602 target_ = oracle->GetCallNewTarget(this);
603 }
604}
605
606
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000607void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
ager@chromium.org378b34e2011-01-28 08:04:38 +0000608 TypeInfo info = oracle->CompareType(this);
609 if (info.IsSmi()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000610 compare_type_ = SMI_ONLY;
ager@chromium.org378b34e2011-01-28 08:04:38 +0000611 } else if (info.IsNonPrimitive()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000612 compare_type_ = OBJECT_ONLY;
613 } else {
614 ASSERT(compare_type_ == NONE);
615 }
616}
617
618
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000619void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
620 receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(this)
621 ? oracle->GetObjectLiteralStoreMap(this)
622 : Handle<Map>::null();
623}
624
625
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000626// ----------------------------------------------------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000627// Implementation of AstVisitor
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000628
lrn@chromium.org25156de2010-04-06 13:10:27 +0000629bool AstVisitor::CheckStackOverflow() {
630 if (stack_overflow_) return true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000631 StackLimitCheck check(isolate_);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000632 if (!check.HasOverflowed()) return false;
633 return (stack_overflow_ = true);
634}
635
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000636
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000637void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
638 for (int i = 0; i < declarations->length(); i++) {
639 Visit(declarations->at(i));
640 }
641}
642
643
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000644void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000645 for (int i = 0; i < statements->length(); i++) {
646 Visit(statements->at(i));
647 }
648}
649
650
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000651void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652 for (int i = 0; i < expressions->length(); i++) {
653 // The variable statement visiting code may pass NULL expressions
654 // to this code. Maybe this should be handled by introducing an
655 // undefined expression or literal? Revisit this code if this
656 // changes
657 Expression* expression = expressions->at(i);
658 if (expression != NULL) Visit(expression);
659 }
660}
661
662
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000663// ----------------------------------------------------------------------------
664// Regular expressions
665
666#define MAKE_ACCEPT(Name) \
667 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
668 return visitor->Visit##Name(this, data); \
669 }
670FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
671#undef MAKE_ACCEPT
672
673#define MAKE_TYPE_CASE(Name) \
674 RegExp##Name* RegExpTree::As##Name() { \
675 return NULL; \
676 } \
677 bool RegExpTree::Is##Name() { return false; }
678FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
679#undef MAKE_TYPE_CASE
680
681#define MAKE_TYPE_CASE(Name) \
682 RegExp##Name* RegExp##Name::As##Name() { \
683 return this; \
684 } \
685 bool RegExp##Name::Is##Name() { return true; }
686FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
687#undef MAKE_TYPE_CASE
688
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000689
ager@chromium.org32912102009-01-16 10:38:43 +0000690static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
691 Interval result = Interval::Empty();
692 for (int i = 0; i < children->length(); i++)
693 result = result.Union(children->at(i)->CaptureRegisters());
694 return result;
695}
696
697
698Interval RegExpAlternative::CaptureRegisters() {
699 return ListCaptureRegisters(nodes());
700}
701
702
703Interval RegExpDisjunction::CaptureRegisters() {
704 return ListCaptureRegisters(alternatives());
705}
706
707
708Interval RegExpLookahead::CaptureRegisters() {
709 return body()->CaptureRegisters();
710}
711
712
713Interval RegExpCapture::CaptureRegisters() {
714 Interval self(StartRegister(index()), EndRegister(index()));
715 return self.Union(body()->CaptureRegisters());
716}
717
718
719Interval RegExpQuantifier::CaptureRegisters() {
720 return body()->CaptureRegisters();
721}
722
723
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000724bool RegExpAssertion::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000725 return type() == RegExpAssertion::START_OF_INPUT;
726}
727
728
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000729bool RegExpAssertion::IsAnchoredAtEnd() {
730 return type() == RegExpAssertion::END_OF_INPUT;
731}
732
733
734bool RegExpAlternative::IsAnchoredAtStart() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000735 ZoneList<RegExpTree*>* nodes = this->nodes();
736 for (int i = 0; i < nodes->length(); i++) {
737 RegExpTree* node = nodes->at(i);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000738 if (node->IsAnchoredAtStart()) { return true; }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000739 if (node->max_match() > 0) { return false; }
740 }
741 return false;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000742}
743
744
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000745bool RegExpAlternative::IsAnchoredAtEnd() {
746 ZoneList<RegExpTree*>* nodes = this->nodes();
747 for (int i = nodes->length() - 1; i >= 0; i--) {
748 RegExpTree* node = nodes->at(i);
749 if (node->IsAnchoredAtEnd()) { return true; }
750 if (node->max_match() > 0) { return false; }
751 }
752 return false;
753}
754
755
756bool RegExpDisjunction::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000757 ZoneList<RegExpTree*>* alternatives = this->alternatives();
758 for (int i = 0; i < alternatives->length(); i++) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000759 if (!alternatives->at(i)->IsAnchoredAtStart())
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000760 return false;
761 }
762 return true;
763}
764
765
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000766bool RegExpDisjunction::IsAnchoredAtEnd() {
767 ZoneList<RegExpTree*>* alternatives = this->alternatives();
768 for (int i = 0; i < alternatives->length(); i++) {
769 if (!alternatives->at(i)->IsAnchoredAtEnd())
770 return false;
771 }
772 return true;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000773}
774
775
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000776bool RegExpLookahead::IsAnchoredAtStart() {
777 return is_positive() && body()->IsAnchoredAtStart();
778}
779
780
781bool RegExpCapture::IsAnchoredAtStart() {
782 return body()->IsAnchoredAtStart();
783}
784
785
786bool RegExpCapture::IsAnchoredAtEnd() {
787 return body()->IsAnchoredAtEnd();
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000788}
789
790
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000791// Convert regular expression trees to a simple sexp representation.
792// This representation should be different from the input grammar
793// in as many cases as possible, to make it more difficult for incorrect
794// parses to look as correct ones which is likely if the input and
795// output formats are alike.
796class RegExpUnparser: public RegExpVisitor {
797 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000798 explicit RegExpUnparser(Zone* zone);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000799 void VisitCharacterRange(CharacterRange that);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000800 SmartArrayPointer<const char> ToString() { return stream_.ToCString(); }
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000801#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, void* data);
802 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
803#undef MAKE_CASE
804 private:
805 StringStream* stream() { return &stream_; }
806 HeapStringAllocator alloc_;
807 StringStream stream_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000808 Zone* zone_;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000809};
810
811
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000812RegExpUnparser::RegExpUnparser(Zone* zone) : stream_(&alloc_), zone_(zone) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000813}
814
815
816void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
817 stream()->Add("(|");
818 for (int i = 0; i < that->alternatives()->length(); i++) {
819 stream()->Add(" ");
820 that->alternatives()->at(i)->Accept(this, data);
821 }
822 stream()->Add(")");
823 return NULL;
824}
825
826
827void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
828 stream()->Add("(:");
829 for (int i = 0; i < that->nodes()->length(); i++) {
830 stream()->Add(" ");
831 that->nodes()->at(i)->Accept(this, data);
832 }
833 stream()->Add(")");
834 return NULL;
835}
836
837
838void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
839 stream()->Add("%k", that.from());
840 if (!that.IsSingleton()) {
841 stream()->Add("-%k", that.to());
842 }
843}
844
845
846
847void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
848 void* data) {
849 if (that->is_negated())
850 stream()->Add("^");
851 stream()->Add("[");
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000852 for (int i = 0; i < that->ranges(zone_)->length(); i++) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000853 if (i > 0) stream()->Add(" ");
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000854 VisitCharacterRange(that->ranges(zone_)->at(i));
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000855 }
856 stream()->Add("]");
857 return NULL;
858}
859
860
861void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
862 switch (that->type()) {
863 case RegExpAssertion::START_OF_INPUT:
864 stream()->Add("@^i");
865 break;
866 case RegExpAssertion::END_OF_INPUT:
867 stream()->Add("@$i");
868 break;
869 case RegExpAssertion::START_OF_LINE:
870 stream()->Add("@^l");
871 break;
872 case RegExpAssertion::END_OF_LINE:
873 stream()->Add("@$l");
874 break;
875 case RegExpAssertion::BOUNDARY:
876 stream()->Add("@b");
877 break;
878 case RegExpAssertion::NON_BOUNDARY:
879 stream()->Add("@B");
880 break;
881 }
882 return NULL;
883}
884
885
886void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
887 stream()->Add("'");
888 Vector<const uc16> chardata = that->data();
889 for (int i = 0; i < chardata.length(); i++) {
890 stream()->Add("%k", chardata[i]);
891 }
892 stream()->Add("'");
893 return NULL;
894}
895
896
897void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
898 if (that->elements()->length() == 1) {
899 that->elements()->at(0).data.u_atom->Accept(this, data);
900 } else {
901 stream()->Add("(!");
902 for (int i = 0; i < that->elements()->length(); i++) {
903 stream()->Add(" ");
904 that->elements()->at(i).data.u_atom->Accept(this, data);
905 }
906 stream()->Add(")");
907 }
908 return NULL;
909}
910
911
912void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
913 stream()->Add("(# %i ", that->min());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000914 if (that->max() == RegExpTree::kInfinity) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000915 stream()->Add("- ");
916 } else {
917 stream()->Add("%i ", that->max());
918 }
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000919 stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000920 that->body()->Accept(this, data);
921 stream()->Add(")");
922 return NULL;
923}
924
925
926void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
927 stream()->Add("(^ ");
928 that->body()->Accept(this, data);
929 stream()->Add(")");
930 return NULL;
931}
932
933
934void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
935 stream()->Add("(-> ");
936 stream()->Add(that->is_positive() ? "+ " : "- ");
937 that->body()->Accept(this, data);
938 stream()->Add(")");
939 return NULL;
940}
941
942
943void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
944 void* data) {
945 stream()->Add("(<- %i)", that->index());
946 return NULL;
947}
948
949
950void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
951 stream()->Put('%');
952 return NULL;
953}
954
955
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000956SmartArrayPointer<const char> RegExpTree::ToString(Zone* zone) {
957 RegExpUnparser unparser(zone);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000958 Accept(&unparser, NULL);
959 return unparser.ToString();
960}
961
962
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000963RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
964 : alternatives_(alternatives) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000965 ASSERT(alternatives->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000966 RegExpTree* first_alternative = alternatives->at(0);
967 min_match_ = first_alternative->min_match();
968 max_match_ = first_alternative->max_match();
969 for (int i = 1; i < alternatives->length(); i++) {
970 RegExpTree* alternative = alternatives->at(i);
971 min_match_ = Min(min_match_, alternative->min_match());
972 max_match_ = Max(max_match_, alternative->max_match());
973 }
974}
975
976
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000977static int IncreaseBy(int previous, int increase) {
978 if (RegExpTree::kInfinity - previous < increase) {
979 return RegExpTree::kInfinity;
980 } else {
981 return previous + increase;
982 }
983}
984
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000985RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
986 : nodes_(nodes) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000987 ASSERT(nodes->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000988 min_match_ = 0;
989 max_match_ = 0;
990 for (int i = 0; i < nodes->length(); i++) {
991 RegExpTree* node = nodes->at(i);
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000992 int node_min_match = node->min_match();
993 min_match_ = IncreaseBy(min_match_, node_min_match);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000994 int node_max_match = node->max_match();
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000995 max_match_ = IncreaseBy(max_match_, node_max_match);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000996 }
997}
998
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000999
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001000CaseClause::CaseClause(Isolate* isolate,
1001 Expression* label,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001002 ZoneList<Statement*>* statements,
1003 int pos)
1004 : label_(label),
1005 statements_(statements),
1006 position_(pos),
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001007 compare_type_(NONE),
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001008 compare_id_(AstNode::GetNextId(isolate)),
1009 entry_id_(AstNode::GetNextId(isolate)) {
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001010}
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001011
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001012
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001013#define REGULAR_NODE(NodeType) \
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001014 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1015 increase_node_count(); \
1016 }
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001017#define DONT_OPTIMIZE_NODE(NodeType) \
1018 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1019 increase_node_count(); \
1020 add_flag(kDontOptimize); \
1021 add_flag(kDontInline); \
1022 add_flag(kDontSelfOptimize); \
1023 }
1024#define DONT_INLINE_NODE(NodeType) \
1025 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1026 increase_node_count(); \
1027 add_flag(kDontInline); \
1028 }
1029#define DONT_SELFOPTIMIZE_NODE(NodeType) \
1030 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1031 increase_node_count(); \
1032 add_flag(kDontSelfOptimize); \
1033 }
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001034#define DONT_CACHE_NODE(NodeType) \
1035 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1036 increase_node_count(); \
1037 add_flag(kDontOptimize); \
1038 add_flag(kDontInline); \
1039 add_flag(kDontSelfOptimize); \
1040 add_flag(kDontCache); \
1041 }
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001042
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001043REGULAR_NODE(VariableDeclaration)
1044REGULAR_NODE(FunctionDeclaration)
1045REGULAR_NODE(Block)
1046REGULAR_NODE(ExpressionStatement)
1047REGULAR_NODE(EmptyStatement)
1048REGULAR_NODE(IfStatement)
1049REGULAR_NODE(ContinueStatement)
1050REGULAR_NODE(BreakStatement)
1051REGULAR_NODE(ReturnStatement)
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00001052REGULAR_NODE(SwitchStatement)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001053REGULAR_NODE(Conditional)
1054REGULAR_NODE(Literal)
1055REGULAR_NODE(ObjectLiteral)
yangguo@chromium.org9c741c82012-06-28 15:04:22 +00001056REGULAR_NODE(RegExpLiteral)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001057REGULAR_NODE(Assignment)
1058REGULAR_NODE(Throw)
1059REGULAR_NODE(Property)
1060REGULAR_NODE(UnaryOperation)
1061REGULAR_NODE(CountOperation)
1062REGULAR_NODE(BinaryOperation)
1063REGULAR_NODE(CompareOperation)
1064REGULAR_NODE(ThisFunction)
1065REGULAR_NODE(Call)
1066REGULAR_NODE(CallNew)
1067// In theory, for VariableProxy we'd have to add:
1068// if (node->var()->IsLookupSlot()) add_flag(kDontInline);
1069// But node->var() is usually not bound yet at VariableProxy creation time, and
1070// LOOKUP variables only result from constructs that cannot be inlined anyway.
1071REGULAR_NODE(VariableProxy)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001072
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001073// We currently do not optimize any modules. Note in particular, that module
1074// instance objects associated with ModuleLiterals are allocated during
1075// scope resolution, and references to them are embedded into the code.
1076// That code may hence neither be cached nor re-compiled.
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001077DONT_OPTIMIZE_NODE(ModuleDeclaration)
1078DONT_OPTIMIZE_NODE(ImportDeclaration)
1079DONT_OPTIMIZE_NODE(ExportDeclaration)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001080DONT_OPTIMIZE_NODE(ModuleVariable)
1081DONT_OPTIMIZE_NODE(ModulePath)
1082DONT_OPTIMIZE_NODE(ModuleUrl)
1083DONT_OPTIMIZE_NODE(WithStatement)
1084DONT_OPTIMIZE_NODE(TryCatchStatement)
1085DONT_OPTIMIZE_NODE(TryFinallyStatement)
1086DONT_OPTIMIZE_NODE(DebuggerStatement)
1087DONT_OPTIMIZE_NODE(SharedFunctionInfoLiteral)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001088
mstarzinger@chromium.orgc6d9cee2012-07-03 10:03:19 +00001089DONT_INLINE_NODE(ArrayLiteral) // TODO(1322): Allow materialized literals.
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001090DONT_INLINE_NODE(FunctionLiteral)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001091
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001092DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
1093DONT_SELFOPTIMIZE_NODE(WhileStatement)
1094DONT_SELFOPTIMIZE_NODE(ForStatement)
1095DONT_SELFOPTIMIZE_NODE(ForInStatement)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001096
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001097DONT_CACHE_NODE(ModuleLiteral)
1098
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001099void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
1100 increase_node_count();
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001101 if (node->is_jsruntime()) {
1102 // Don't try to inline JS runtime calls because we don't (currently) even
1103 // optimize them.
1104 add_flag(kDontInline);
1105 } else if (node->function()->intrinsic_type == Runtime::INLINE &&
1106 (node->name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
1107 node->name()->IsEqualTo(CStrVector("_Arguments")))) {
1108 // Don't inline the %_ArgumentsLength or %_Arguments because their
1109 // implementation will not work. There is no stack frame to get them
1110 // from.
1111 add_flag(kDontInline);
1112 }
1113}
1114
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001115#undef REGULAR_NODE
1116#undef DONT_OPTIMIZE_NODE
1117#undef DONT_INLINE_NODE
1118#undef DONT_SELFOPTIMIZE_NODE
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001119#undef DONT_CACHE_NODE
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001120
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001121
1122Handle<String> Literal::ToString() {
1123 if (handle_->IsString()) return Handle<String>::cast(handle_);
1124 ASSERT(handle_->IsNumber());
1125 char arr[100];
1126 Vector<char> buffer(arr, ARRAY_SIZE(arr));
1127 const char* str;
1128 if (handle_->IsSmi()) {
1129 // Optimization only, the heap number case would subsume this.
1130 OS::SNPrintF(buffer, "%d", Smi::cast(*handle_)->value());
1131 str = arr;
1132 } else {
1133 str = DoubleToCString(handle_->Number(), buffer);
1134 }
1135 return FACTORY->NewStringFromAscii(CStrVector(str));
1136}
1137
1138
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001139} } // namespace v8::internal