blob: 0d667cc168812d0b3f487bf422f1bcf096ac4d1c [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
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000030#include <cmath> // For isfinite.
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000031#include "builtins.h"
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +000032#include "code-stubs.h"
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000033#include "contexts.h"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000034#include "conversions.h"
35#include "hashmap.h"
ager@chromium.org3811b432009-10-28 14:53:37 +000036#include "parser.h"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000037#include "property-details.h"
38#include "property.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039#include "scopes.h"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000040#include "string-stream.h"
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000041#include "type-info.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000042
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046// ----------------------------------------------------------------------------
47// All the Accept member functions for each syntax tree node type.
48
lrn@chromium.org25156de2010-04-06 13:10:27 +000049#define DECL_ACCEPT(type) \
50 void type::Accept(AstVisitor* v) { v->Visit##type(this); }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000051AST_NODE_LIST(DECL_ACCEPT)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052#undef DECL_ACCEPT
53
54
55// ----------------------------------------------------------------------------
56// Implementation of other node functionality.
57
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000058
59bool Expression::IsSmiLiteral() {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000060 return AsLiteral() != NULL && AsLiteral()->value()->IsSmi();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000061}
62
63
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000064bool Expression::IsStringLiteral() {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000065 return AsLiteral() != NULL && AsLiteral()->value()->IsString();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000066}
67
68
69bool Expression::IsNullLiteral() {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000070 return AsLiteral() != NULL && AsLiteral()->value()->IsNull();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000071}
72
73
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +000074bool Expression::IsUndefinedLiteral(Isolate* isolate) {
75 VariableProxy* var_proxy = AsVariableProxy();
76 if (var_proxy == NULL) return false;
77 Variable* var = var_proxy->var();
78 // The global identifier "undefined" is immutable. Everything
79 // else could be reassigned.
80 return var != NULL && var->location() == Variable::UNALLOCATED &&
81 var_proxy->name()->Equals(isolate->heap()->undefined_string());
danno@chromium.orgca29dd82013-04-26 11:59:48 +000082}
83
84
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000085VariableProxy::VariableProxy(Isolate* isolate, Variable* var, int position)
86 : Expression(isolate, position),
rossberg@chromium.org717967f2011-07-20 13:44:42 +000087 name_(var->name()),
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000088 var_(NULL), // Will be set by the call to BindTo.
89 is_this_(var->is_this()),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000090 is_trivial_(false),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +000091 is_lvalue_(false),
erik.corry@gmail.combbceb572012-03-09 10:52:05 +000092 interface_(var->interface()) {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000093 BindTo(var);
94}
95
96
rossberg@chromium.org717967f2011-07-20 13:44:42 +000097VariableProxy::VariableProxy(Isolate* isolate,
98 Handle<String> name,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000099 bool is_this,
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000100 Interface* interface,
101 int position)
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000102 : Expression(isolate, position),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000103 name_(name),
104 var_(NULL),
105 is_this_(is_this),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000106 is_trivial_(false),
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000107 is_lvalue_(false),
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000108 interface_(interface) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000109 // Names must be canonicalized for fast equality checks.
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000110 ASSERT(name->IsInternalizedString());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111}
112
113
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114void VariableProxy::BindTo(Variable* var) {
115 ASSERT(var_ == NULL); // must be bound only once
116 ASSERT(var != NULL); // must bind
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000117 ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000118 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
119 // Ideally CONST-ness should match. However, this is very hard to achieve
120 // because we don't know the exact semantics of conflicting (const and
121 // non-const) multiple variable declarations, const vars introduced via
122 // eval() etc. Const-ness and variable declarations are a complete mess
123 // in JS. Sigh...
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124 var_ = var;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000125 var->set_is_used(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000126}
127
128
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000129Assignment::Assignment(Isolate* isolate,
130 Token::Value op,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000131 Expression* target,
132 Expression* value,
133 int pos)
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000134 : Expression(isolate, pos),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000135 op_(op),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000136 target_(target),
137 value_(value),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000138 binary_operation_(NULL),
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000139 assignment_id_(GetNextId(isolate)),
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000140 is_monomorphic_(false),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000141 is_uninitialized_(false),
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000142 store_mode_(STANDARD_STORE) { }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000143
144
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000145Token::Value Assignment::binary_op() const {
146 switch (op_) {
147 case Token::ASSIGN_BIT_OR: return Token::BIT_OR;
148 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR;
149 case Token::ASSIGN_BIT_AND: return Token::BIT_AND;
150 case Token::ASSIGN_SHL: return Token::SHL;
151 case Token::ASSIGN_SAR: return Token::SAR;
152 case Token::ASSIGN_SHR: return Token::SHR;
153 case Token::ASSIGN_ADD: return Token::ADD;
154 case Token::ASSIGN_SUB: return Token::SUB;
155 case Token::ASSIGN_MUL: return Token::MUL;
156 case Token::ASSIGN_DIV: return Token::DIV;
157 case Token::ASSIGN_MOD: return Token::MOD;
158 default: UNREACHABLE();
159 }
160 return Token::ILLEGAL;
161}
162
163
164bool FunctionLiteral::AllowsLazyCompilation() {
165 return scope()->AllowsLazyCompilation();
166}
167
168
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000169bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
170 return scope()->AllowsLazyCompilationWithoutContext();
171}
172
173
danno@chromium.orgc612e022011-11-10 11:38:15 +0000174int FunctionLiteral::start_position() const {
175 return scope()->start_position();
176}
177
178
179int FunctionLiteral::end_position() const {
180 return scope()->end_position();
181}
182
183
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000184LanguageMode FunctionLiteral::language_mode() const {
185 return scope()->language_mode();
danno@chromium.orgc612e022011-11-10 11:38:15 +0000186}
187
188
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000189ObjectLiteralProperty::ObjectLiteralProperty(Literal* key,
190 Expression* value,
191 Isolate* isolate) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000192 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193 key_ = key;
194 value_ = value;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000195 Object* k = *key->value();
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000196 if (k->IsInternalizedString() &&
197 isolate->heap()->proto_string()->Equals(String::cast(k))) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198 kind_ = PROTOTYPE;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000199 } else if (value_->AsMaterializedLiteral() != NULL) {
200 kind_ = MATERIALIZED_LITERAL;
201 } else if (value_->AsLiteral() != NULL) {
202 kind_ = CONSTANT;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000203 } else {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000204 kind_ = COMPUTED;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205 }
206}
207
208
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000209ObjectLiteralProperty::ObjectLiteralProperty(bool is_getter,
210 FunctionLiteral* value) {
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000211 emit_store_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 value_ = value;
213 kind_ = is_getter ? GETTER : SETTER;
214}
215
216
ager@chromium.org3811b432009-10-28 14:53:37 +0000217bool ObjectLiteral::Property::IsCompileTimeValue() {
218 return kind_ == CONSTANT ||
219 (kind_ == MATERIALIZED_LITERAL &&
220 CompileTimeValue::IsCompileTimeValue(value_));
221}
222
223
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000224void ObjectLiteral::Property::set_emit_store(bool emit_store) {
225 emit_store_ = emit_store;
226}
227
228
229bool ObjectLiteral::Property::emit_store() {
230 return emit_store_;
231}
232
233
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000234void ObjectLiteral::CalculateEmitStore(Zone* zone) {
235 ZoneAllocationPolicy allocator(zone);
236
237 ZoneHashMap table(Literal::Match, ZoneHashMap::kDefaultHashMapCapacity,
238 allocator);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000239 for (int i = properties()->length() - 1; i >= 0; i--) {
240 ObjectLiteral::Property* property = properties()->at(i);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000241 Literal* literal = property->key();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000242 if (literal->value()->IsNull()) continue;
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000243 uint32_t hash = literal->Hash();
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000244 // If the key of a computed property is in the table, do not emit
245 // a store for the property later.
danno@chromium.orgc00ec2b2013-08-14 17:13:49 +0000246 if ((property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL ||
247 property->kind() == ObjectLiteral::Property::COMPUTED) &&
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000248 table.Lookup(literal, hash, false, allocator) != NULL) {
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000249 property->set_emit_store(false);
250 } else {
251 // Add key to the table.
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000252 table.Lookup(literal, hash, true, allocator);
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000253 }
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000254 }
255}
256
257
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000258void TargetCollector::AddTarget(Label* target, Zone* zone) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000259 // Add the label to the collector, but discard duplicates.
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000260 int length = targets_.length();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000261 for (int i = 0; i < length; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000262 if (targets_[i] == target) return;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000264 targets_.Add(target, zone);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265}
266
267
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000268void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
269 // TODO(olivf) If this Operation is used in a test context, then the
270 // expression has a ToBoolean stub and we want to collect the type
271 // information. However the GraphBuilder expects it to be on the instruction
272 // corresponding to the TestContext, therefore we have to store it here and
273 // not on the operand.
274 set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
275}
276
277
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000278void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
279 // TODO(olivf) If this Operation is used in a test context, then the right
280 // hand side has a ToBoolean stub and we want to collect the type information.
281 // However the GraphBuilder expects it to be on the instruction corresponding
282 // to the TestContext, therefore we have to store it here and not on the
283 // right hand operand.
284 set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
285}
286
287
ricow@chromium.org65fae842010-08-25 15:26:24 +0000288bool BinaryOperation::ResultOverwriteAllowed() {
289 switch (op_) {
290 case Token::COMMA:
291 case Token::OR:
292 case Token::AND:
293 return false;
294 case Token::BIT_OR:
295 case Token::BIT_XOR:
296 case Token::BIT_AND:
297 case Token::SHL:
298 case Token::SAR:
299 case Token::SHR:
300 case Token::ADD:
301 case Token::SUB:
302 case Token::MUL:
303 case Token::DIV:
304 case Token::MOD:
305 return true;
306 default:
307 UNREACHABLE();
308 }
309 return false;
310}
311
312
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000313static bool IsTypeof(Expression* expr) {
314 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
315 return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
316}
317
318
319// Check for the pattern: typeof <expression> equals <string literal>.
320static bool MatchLiteralCompareTypeof(Expression* left,
321 Token::Value op,
322 Expression* right,
323 Expression** expr,
324 Handle<String>* check) {
325 if (IsTypeof(left) && right->IsStringLiteral() && Token::IsEqualityOp(op)) {
326 *expr = left->AsUnaryOperation()->expression();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000327 *check = Handle<String>::cast(right->AsLiteral()->value());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000328 return true;
329 }
330 return false;
331}
332
333
ager@chromium.org04921a82011-06-27 13:21:41 +0000334bool CompareOperation::IsLiteralCompareTypeof(Expression** expr,
335 Handle<String>* check) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000336 return MatchLiteralCompareTypeof(left_, op_, right_, expr, check) ||
337 MatchLiteralCompareTypeof(right_, op_, left_, expr, check);
338}
ager@chromium.org04921a82011-06-27 13:21:41 +0000339
ager@chromium.org04921a82011-06-27 13:21:41 +0000340
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000341static bool IsVoidOfLiteral(Expression* expr) {
342 UnaryOperation* maybe_unary = expr->AsUnaryOperation();
343 return maybe_unary != NULL &&
344 maybe_unary->op() == Token::VOID &&
345 maybe_unary->expression()->AsLiteral() != NULL;
346}
347
348
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000349// Check for the pattern: void <literal> equals <expression> or
350// undefined equals <expression>
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000351static bool MatchLiteralCompareUndefined(Expression* left,
352 Token::Value op,
353 Expression* right,
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +0000354 Expression** expr,
355 Isolate* isolate) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000356 if (IsVoidOfLiteral(left) && Token::IsEqualityOp(op)) {
357 *expr = right;
ager@chromium.org04921a82011-06-27 13:21:41 +0000358 return true;
359 }
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +0000360 if (left->IsUndefinedLiteral(isolate) && Token::IsEqualityOp(op)) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000361 *expr = right;
362 return true;
363 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000364 return false;
365}
366
367
jkummerow@chromium.org96a3c512013-07-18 17:02:47 +0000368bool CompareOperation::IsLiteralCompareUndefined(
369 Expression** expr, Isolate* isolate) {
370 return MatchLiteralCompareUndefined(left_, op_, right_, expr, isolate) ||
371 MatchLiteralCompareUndefined(right_, op_, left_, expr, isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000372}
ager@chromium.org04921a82011-06-27 13:21:41 +0000373
ager@chromium.org04921a82011-06-27 13:21:41 +0000374
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000375// Check for the pattern: null equals <expression>
376static bool MatchLiteralCompareNull(Expression* left,
377 Token::Value op,
378 Expression* right,
379 Expression** expr) {
380 if (left->IsNullLiteral() && Token::IsEqualityOp(op)) {
381 *expr = right;
ager@chromium.org04921a82011-06-27 13:21:41 +0000382 return true;
383 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000384 return false;
385}
386
387
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000388bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
389 return MatchLiteralCompareNull(left_, op_, right_, expr) ||
390 MatchLiteralCompareNull(right_, op_, left_, expr);
391}
392
393
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394// ----------------------------------------------------------------------------
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000395// Inlining support
396
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000397bool Declaration::IsInlineable() const {
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000398 return proxy()->var()->IsStackAllocated();
399}
400
ulan@chromium.org812308e2012-02-29 15:58:45 +0000401bool FunctionDeclaration::IsInlineable() const {
402 return false;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000403}
404
405
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000406// ----------------------------------------------------------------------------
407// Recording of type feedback
408
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000409// TODO(rossberg): all RecordTypeFeedback functions should disappear
410// once we use the common type field in the AST consistently.
411
412
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000413void ForInStatement::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
414 for_in_type_ = static_cast<ForInType>(oracle->ForInType(this));
415}
416
417
418void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
419 to_boolean_types_ = oracle->ToBooleanTypes(test_id());
420}
421
422
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000423void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
424 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000425 // Record type feedback from the oracle in the AST.
jkummerow@chromium.org531dfe82012-03-20 13:01:16 +0000426 is_uninitialized_ = oracle->LoadIsUninitialized(this);
427 if (is_uninitialized_) return;
428
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000429 is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000430 receiver_types_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000431 if (key()->IsPropertyName()) {
mvstanton@chromium.org6bec0092013-01-23 13:46:53 +0000432 FunctionPrototypeStub proto_stub(Code::LOAD_IC);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000433 if (oracle->LoadIsStub(this, &proto_stub)) {
fschneider@chromium.org9e3e0b62011-01-03 10:16:46 +0000434 is_function_prototype_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000435 } else {
436 Literal* lit_key = key()->AsLiteral();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000437 ASSERT(lit_key != NULL && lit_key->value()->IsString());
438 Handle<String> name = Handle<String>::cast(lit_key->value());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000439 oracle->LoadReceiverTypes(this, name, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000440 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000441 } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000442 is_string_access_ = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000443 } else if (is_monomorphic_) {
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000444 receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this), zone);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000445 } else if (oracle->LoadIsPolymorphic(this)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000446 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000447 oracle->CollectKeyedReceiverTypes(PropertyFeedbackId(), &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000448 }
449}
450
451
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000452void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle,
453 Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000454 Property* prop = target()->AsProperty();
455 ASSERT(prop != NULL);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000456 TypeFeedbackId id = AssignmentFeedbackId();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000457 is_uninitialized_ = oracle->StoreIsUninitialized(id);
458 if (is_uninitialized_) return;
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000459 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(id);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000460 receiver_types_.Clear();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000461 if (prop->key()->IsPropertyName()) {
462 Literal* lit_key = prop->key()->AsLiteral();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000463 ASSERT(lit_key != NULL && lit_key->value()->IsString());
464 Handle<String> name = Handle<String>::cast(lit_key->value());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000465 oracle->StoreReceiverTypes(this, name, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000466 } else if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000467 // Record receiver type for monomorphic keyed stores.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000468 receiver_types_.Add(oracle->StoreMonomorphicReceiverType(id), zone);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000469 store_mode_ = oracle->GetStoreMode(id);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000470 } else if (oracle->StoreIsKeyedPolymorphic(id)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000471 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000472 oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000473 store_mode_ = oracle->GetStoreMode(id);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000474 }
475}
476
477
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000478void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle,
479 Zone* zone) {
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000480 TypeFeedbackId id = CountStoreFeedbackId();
481 is_monomorphic_ = oracle->StoreIsMonomorphicNormal(id);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000482 receiver_types_.Clear();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000483 if (is_monomorphic_) {
whesse@chromium.org7b260152011-06-20 15:33:18 +0000484 // Record receiver type for monomorphic keyed stores.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000485 receiver_types_.Add(
486 oracle->StoreMonomorphicReceiverType(id), zone);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000487 } else if (oracle->StoreIsKeyedPolymorphic(id)) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000488 receiver_types_.Reserve(kMaxKeyedPolymorphism, zone);
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000489 oracle->CollectKeyedReceiverTypes(id, &receiver_types_);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000490 } else {
491 oracle->CollectPolymorphicStoreReceiverTypes(id, &receiver_types_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000492 }
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +0000493 store_mode_ = oracle->GetStoreMode(id);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000494 type_ = oracle->IncrementType(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000495}
496
497
498void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
danno@chromium.org41728482013-06-12 22:31:22 +0000499 compare_type_ = oracle->ClauseType(CompareId());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000500}
501
502
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000503bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000504 // If there is an interceptor, we can't compute the target for a direct call.
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000505 if (type->has_named_interceptor()) return false;
506
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000507 if (check_type_ == RECEIVER_MAP_CHECK) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000508 // For primitive checks the holder is set up to point to the corresponding
509 // prototype object, i.e. one step of the algorithm below has been already
510 // performed. For non-primitive checks we clear it to allow computing
511 // targets for polymorphic calls.
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000512 holder_ = Handle<JSObject>::null();
513 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000514 LookupResult lookup(type->GetIsolate());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000515 while (true) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000516 // If a dictionary map is found in the prototype chain before the actual
517 // target, a new target can always appear. In that case, bail out.
518 // TODO(verwaest): Alternatively a runtime negative lookup on the normal
519 // receiver or prototype could be added.
520 if (type->is_dictionary_map()) return false;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000521 type->LookupDescriptor(NULL, *name, &lookup);
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000522 if (lookup.IsFound()) {
523 switch (lookup.type()) {
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000524 case CONSTANT: {
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000525 // We surely know the target for a constant function.
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000526 Handle<Object> constant(lookup.GetConstantFromMap(*type),
527 type->GetIsolate());
528 if (constant->IsJSFunction()) {
529 target_ = Handle<JSFunction>::cast(constant);
530 return true;
531 }
532 // Fall through.
533 }
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000534 case NORMAL:
535 case FIELD:
536 case CALLBACKS:
537 case HANDLER:
538 case INTERCEPTOR:
539 // We don't know the target.
540 return false;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +0000541 case TRANSITION:
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000542 case NONEXISTENT:
543 UNREACHABLE();
544 break;
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000545 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000546 }
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000547 // If we reach the end of the prototype chain, we don't know the target.
548 if (!type->prototype()->IsJSObject()) return false;
549 // Go up the prototype chain, recording where we are currently.
550 holder_ = Handle<JSObject>(JSObject::cast(type->prototype()));
551 type = Handle<Map>(holder()->map());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000552 }
553}
554
555
556bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000557 LookupResult* lookup) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000558 target_ = Handle<JSFunction>::null();
danno@chromium.org41728482013-06-12 22:31:22 +0000559 cell_ = Handle<Cell>::null();
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000560 ASSERT(lookup->IsFound() &&
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000561 lookup->type() == NORMAL &&
562 lookup->holder() == *global);
danno@chromium.org41728482013-06-12 22:31:22 +0000563 cell_ = Handle<Cell>(global->GetPropertyCell(lookup));
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000564 if (cell_->value()->IsJSFunction()) {
565 Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
566 // If the function is in new space we assume it's more likely to
567 // change and thus prefer the general IC code.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000568 if (!lookup->isolate()->heap()->InNewSpace(*candidate)) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000569 target_ = candidate;
570 return true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000571 }
572 }
573 return false;
574}
575
576
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000577Handle<JSObject> Call::GetPrototypeForPrimitiveCheck(
578 CheckType check, Isolate* isolate) {
579 v8::internal::Context* native_context = isolate->context()->native_context();
580 JSFunction* function = NULL;
581 switch (check) {
582 case RECEIVER_MAP_CHECK:
583 UNREACHABLE();
584 break;
585 case STRING_CHECK:
586 function = native_context->string_function();
587 break;
588 case SYMBOL_CHECK:
589 function = native_context->symbol_function();
590 break;
591 case NUMBER_CHECK:
592 function = native_context->number_function();
593 break;
594 case BOOLEAN_CHECK:
595 function = native_context->boolean_function();
596 break;
597 }
598 ASSERT(function != NULL);
599 return Handle<JSObject>(JSObject::cast(function->instance_prototype()));
600}
601
602
danno@chromium.org40cb8782011-05-25 07:58:50 +0000603void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
604 CallKind call_kind) {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000605 is_monomorphic_ = oracle->CallIsMonomorphic(this);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000606 Property* property = expression()->AsProperty();
607 if (property == NULL) {
608 // Function call. Specialize for monomorphic calls.
609 if (is_monomorphic_) target_ = oracle->GetCallTarget(this);
610 } else {
611 // Method call. Specialize for the receiver types seen at runtime.
612 Literal* key = property->key()->AsLiteral();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000613 ASSERT(key != NULL && key->value()->IsString());
614 Handle<String> name = Handle<String>::cast(key->value());
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000615 check_type_ = oracle->GetCallCheckType(this);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000616 receiver_types_.Clear();
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000617 if (check_type_ == RECEIVER_MAP_CHECK) {
618 oracle->CallReceiverTypes(this, name, call_kind, &receiver_types_);
619 is_monomorphic_ = is_monomorphic_ && receiver_types_.length() > 0;
620 } else {
621 holder_ = GetPrototypeForPrimitiveCheck(check_type_, oracle->isolate());
622 receiver_types_.Add(handle(holder_->map()), oracle->zone());
623 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000624#ifdef DEBUG
625 if (FLAG_enable_slow_asserts) {
626 int length = receiver_types_.length();
627 for (int i = 0; i < length; i++) {
628 Handle<Map> map = receiver_types_.at(i);
629 ASSERT(!map.is_null() && *map != NULL);
630 }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000631 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000632#endif
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000633 if (is_monomorphic_) {
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000634 Handle<Map> map = receiver_types_.first();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000635 is_monomorphic_ = ComputeTarget(map, name);
636 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000637 }
638}
639
640
ulan@chromium.org967e2702012-02-28 09:49:15 +0000641void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000642 allocation_info_cell_ = oracle->GetCallNewAllocationInfoCell(this);
ulan@chromium.org967e2702012-02-28 09:49:15 +0000643 is_monomorphic_ = oracle->CallNewIsMonomorphic(this);
644 if (is_monomorphic_) {
645 target_ = oracle->GetCallNewTarget(this);
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000646 Object* value = allocation_info_cell_->value();
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000647 ASSERT(!value->IsTheHole());
danno@chromium.orgbee51992013-07-10 14:57:15 +0000648 if (value->IsAllocationSite()) {
649 AllocationSite* site = AllocationSite::cast(value);
650 elements_kind_ = site->GetElementsKind();
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000651 }
ulan@chromium.org967e2702012-02-28 09:49:15 +0000652 }
653}
654
655
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000656void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
657 receiver_type_ = oracle->ObjectLiteralStoreIsMonomorphic(this)
658 ? oracle->GetObjectLiteralStoreMap(this)
659 : Handle<Map>::null();
660}
661
662
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000663// ----------------------------------------------------------------------------
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000664// Implementation of AstVisitor
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000665
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000666void AstVisitor::VisitDeclarations(ZoneList<Declaration*>* declarations) {
667 for (int i = 0; i < declarations->length(); i++) {
668 Visit(declarations->at(i));
669 }
670}
671
672
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000673void AstVisitor::VisitStatements(ZoneList<Statement*>* statements) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 for (int i = 0; i < statements->length(); i++) {
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +0000675 Statement* stmt = statements->at(i);
676 Visit(stmt);
677 if (stmt->IsJump()) break;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000678 }
679}
680
681
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000682void AstVisitor::VisitExpressions(ZoneList<Expression*>* expressions) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683 for (int i = 0; i < expressions->length(); i++) {
684 // The variable statement visiting code may pass NULL expressions
685 // to this code. Maybe this should be handled by introducing an
686 // undefined expression or literal? Revisit this code if this
687 // changes
688 Expression* expression = expressions->at(i);
689 if (expression != NULL) Visit(expression);
690 }
691}
692
693
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000694// ----------------------------------------------------------------------------
695// Regular expressions
696
697#define MAKE_ACCEPT(Name) \
698 void* RegExp##Name::Accept(RegExpVisitor* visitor, void* data) { \
699 return visitor->Visit##Name(this, data); \
700 }
701FOR_EACH_REG_EXP_TREE_TYPE(MAKE_ACCEPT)
702#undef MAKE_ACCEPT
703
704#define MAKE_TYPE_CASE(Name) \
705 RegExp##Name* RegExpTree::As##Name() { \
706 return NULL; \
707 } \
708 bool RegExpTree::Is##Name() { return false; }
709FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
710#undef MAKE_TYPE_CASE
711
712#define MAKE_TYPE_CASE(Name) \
713 RegExp##Name* RegExp##Name::As##Name() { \
714 return this; \
715 } \
716 bool RegExp##Name::Is##Name() { return true; }
717FOR_EACH_REG_EXP_TREE_TYPE(MAKE_TYPE_CASE)
718#undef MAKE_TYPE_CASE
719
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000720
ager@chromium.org32912102009-01-16 10:38:43 +0000721static Interval ListCaptureRegisters(ZoneList<RegExpTree*>* children) {
722 Interval result = Interval::Empty();
723 for (int i = 0; i < children->length(); i++)
724 result = result.Union(children->at(i)->CaptureRegisters());
725 return result;
726}
727
728
729Interval RegExpAlternative::CaptureRegisters() {
730 return ListCaptureRegisters(nodes());
731}
732
733
734Interval RegExpDisjunction::CaptureRegisters() {
735 return ListCaptureRegisters(alternatives());
736}
737
738
739Interval RegExpLookahead::CaptureRegisters() {
740 return body()->CaptureRegisters();
741}
742
743
744Interval RegExpCapture::CaptureRegisters() {
745 Interval self(StartRegister(index()), EndRegister(index()));
746 return self.Union(body()->CaptureRegisters());
747}
748
749
750Interval RegExpQuantifier::CaptureRegisters() {
751 return body()->CaptureRegisters();
752}
753
754
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000755bool RegExpAssertion::IsAnchoredAtStart() {
ulan@chromium.orgdfe53072013-06-06 14:14:51 +0000756 return assertion_type() == RegExpAssertion::START_OF_INPUT;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000757}
758
759
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000760bool RegExpAssertion::IsAnchoredAtEnd() {
ulan@chromium.orgdfe53072013-06-06 14:14:51 +0000761 return assertion_type() == RegExpAssertion::END_OF_INPUT;
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000762}
763
764
765bool RegExpAlternative::IsAnchoredAtStart() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000766 ZoneList<RegExpTree*>* nodes = this->nodes();
767 for (int i = 0; i < nodes->length(); i++) {
768 RegExpTree* node = nodes->at(i);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000769 if (node->IsAnchoredAtStart()) { return true; }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000770 if (node->max_match() > 0) { return false; }
771 }
772 return false;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000773}
774
775
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000776bool RegExpAlternative::IsAnchoredAtEnd() {
777 ZoneList<RegExpTree*>* nodes = this->nodes();
778 for (int i = nodes->length() - 1; i >= 0; i--) {
779 RegExpTree* node = nodes->at(i);
780 if (node->IsAnchoredAtEnd()) { return true; }
781 if (node->max_match() > 0) { return false; }
782 }
783 return false;
784}
785
786
787bool RegExpDisjunction::IsAnchoredAtStart() {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000788 ZoneList<RegExpTree*>* alternatives = this->alternatives();
789 for (int i = 0; i < alternatives->length(); i++) {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000790 if (!alternatives->at(i)->IsAnchoredAtStart())
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000791 return false;
792 }
793 return true;
794}
795
796
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000797bool RegExpDisjunction::IsAnchoredAtEnd() {
798 ZoneList<RegExpTree*>* alternatives = this->alternatives();
799 for (int i = 0; i < alternatives->length(); i++) {
800 if (!alternatives->at(i)->IsAnchoredAtEnd())
801 return false;
802 }
803 return true;
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000804}
805
806
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000807bool RegExpLookahead::IsAnchoredAtStart() {
808 return is_positive() && body()->IsAnchoredAtStart();
809}
810
811
812bool RegExpCapture::IsAnchoredAtStart() {
813 return body()->IsAnchoredAtStart();
814}
815
816
817bool RegExpCapture::IsAnchoredAtEnd() {
818 return body()->IsAnchoredAtEnd();
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000819}
820
821
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000822// Convert regular expression trees to a simple sexp representation.
823// This representation should be different from the input grammar
824// in as many cases as possible, to make it more difficult for incorrect
825// parses to look as correct ones which is likely if the input and
826// output formats are alike.
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000827class RegExpUnparser V8_FINAL : public RegExpVisitor {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000828 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000829 explicit RegExpUnparser(Zone* zone);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000830 void VisitCharacterRange(CharacterRange that);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000831 SmartArrayPointer<const char> ToString() { return stream_.ToCString(); }
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +0000832#define MAKE_CASE(Name) virtual void* Visit##Name(RegExp##Name*, \
833 void* data) V8_OVERRIDE;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000834 FOR_EACH_REG_EXP_TREE_TYPE(MAKE_CASE)
835#undef MAKE_CASE
836 private:
837 StringStream* stream() { return &stream_; }
838 HeapStringAllocator alloc_;
839 StringStream stream_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000840 Zone* zone_;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000841};
842
843
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000844RegExpUnparser::RegExpUnparser(Zone* zone) : stream_(&alloc_), zone_(zone) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000845}
846
847
848void* RegExpUnparser::VisitDisjunction(RegExpDisjunction* that, void* data) {
849 stream()->Add("(|");
850 for (int i = 0; i < that->alternatives()->length(); i++) {
851 stream()->Add(" ");
852 that->alternatives()->at(i)->Accept(this, data);
853 }
854 stream()->Add(")");
855 return NULL;
856}
857
858
859void* RegExpUnparser::VisitAlternative(RegExpAlternative* that, void* data) {
860 stream()->Add("(:");
861 for (int i = 0; i < that->nodes()->length(); i++) {
862 stream()->Add(" ");
863 that->nodes()->at(i)->Accept(this, data);
864 }
865 stream()->Add(")");
866 return NULL;
867}
868
869
870void RegExpUnparser::VisitCharacterRange(CharacterRange that) {
871 stream()->Add("%k", that.from());
872 if (!that.IsSingleton()) {
873 stream()->Add("-%k", that.to());
874 }
875}
876
877
878
879void* RegExpUnparser::VisitCharacterClass(RegExpCharacterClass* that,
880 void* data) {
881 if (that->is_negated())
882 stream()->Add("^");
883 stream()->Add("[");
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000884 for (int i = 0; i < that->ranges(zone_)->length(); i++) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000885 if (i > 0) stream()->Add(" ");
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000886 VisitCharacterRange(that->ranges(zone_)->at(i));
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000887 }
888 stream()->Add("]");
889 return NULL;
890}
891
892
893void* RegExpUnparser::VisitAssertion(RegExpAssertion* that, void* data) {
ulan@chromium.orgdfe53072013-06-06 14:14:51 +0000894 switch (that->assertion_type()) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000895 case RegExpAssertion::START_OF_INPUT:
896 stream()->Add("@^i");
897 break;
898 case RegExpAssertion::END_OF_INPUT:
899 stream()->Add("@$i");
900 break;
901 case RegExpAssertion::START_OF_LINE:
902 stream()->Add("@^l");
903 break;
904 case RegExpAssertion::END_OF_LINE:
905 stream()->Add("@$l");
906 break;
907 case RegExpAssertion::BOUNDARY:
908 stream()->Add("@b");
909 break;
910 case RegExpAssertion::NON_BOUNDARY:
911 stream()->Add("@B");
912 break;
913 }
914 return NULL;
915}
916
917
918void* RegExpUnparser::VisitAtom(RegExpAtom* that, void* data) {
919 stream()->Add("'");
920 Vector<const uc16> chardata = that->data();
921 for (int i = 0; i < chardata.length(); i++) {
922 stream()->Add("%k", chardata[i]);
923 }
924 stream()->Add("'");
925 return NULL;
926}
927
928
929void* RegExpUnparser::VisitText(RegExpText* that, void* data) {
930 if (that->elements()->length() == 1) {
rossberg@chromium.org92597162013-08-23 13:28:00 +0000931 that->elements()->at(0).tree()->Accept(this, data);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000932 } else {
933 stream()->Add("(!");
934 for (int i = 0; i < that->elements()->length(); i++) {
935 stream()->Add(" ");
rossberg@chromium.org92597162013-08-23 13:28:00 +0000936 that->elements()->at(i).tree()->Accept(this, data);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000937 }
938 stream()->Add(")");
939 }
940 return NULL;
941}
942
943
944void* RegExpUnparser::VisitQuantifier(RegExpQuantifier* that, void* data) {
945 stream()->Add("(# %i ", that->min());
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000946 if (that->max() == RegExpTree::kInfinity) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000947 stream()->Add("- ");
948 } else {
949 stream()->Add("%i ", that->max());
950 }
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000951 stream()->Add(that->is_greedy() ? "g " : that->is_possessive() ? "p " : "n ");
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000952 that->body()->Accept(this, data);
953 stream()->Add(")");
954 return NULL;
955}
956
957
958void* RegExpUnparser::VisitCapture(RegExpCapture* that, void* data) {
959 stream()->Add("(^ ");
960 that->body()->Accept(this, data);
961 stream()->Add(")");
962 return NULL;
963}
964
965
966void* RegExpUnparser::VisitLookahead(RegExpLookahead* that, void* data) {
967 stream()->Add("(-> ");
968 stream()->Add(that->is_positive() ? "+ " : "- ");
969 that->body()->Accept(this, data);
970 stream()->Add(")");
971 return NULL;
972}
973
974
975void* RegExpUnparser::VisitBackReference(RegExpBackReference* that,
976 void* data) {
977 stream()->Add("(<- %i)", that->index());
978 return NULL;
979}
980
981
982void* RegExpUnparser::VisitEmpty(RegExpEmpty* that, void* data) {
983 stream()->Put('%');
984 return NULL;
985}
986
987
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000988SmartArrayPointer<const char> RegExpTree::ToString(Zone* zone) {
989 RegExpUnparser unparser(zone);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000990 Accept(&unparser, NULL);
991 return unparser.ToString();
992}
993
994
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000995RegExpDisjunction::RegExpDisjunction(ZoneList<RegExpTree*>* alternatives)
996 : alternatives_(alternatives) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000997 ASSERT(alternatives->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000998 RegExpTree* first_alternative = alternatives->at(0);
999 min_match_ = first_alternative->min_match();
1000 max_match_ = first_alternative->max_match();
1001 for (int i = 1; i < alternatives->length(); i++) {
1002 RegExpTree* alternative = alternatives->at(i);
1003 min_match_ = Min(min_match_, alternative->min_match());
1004 max_match_ = Max(max_match_, alternative->max_match());
1005 }
1006}
1007
1008
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00001009static int IncreaseBy(int previous, int increase) {
1010 if (RegExpTree::kInfinity - previous < increase) {
1011 return RegExpTree::kInfinity;
1012 } else {
1013 return previous + increase;
1014 }
1015}
1016
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001017RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
1018 : nodes_(nodes) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +00001019 ASSERT(nodes->length() > 1);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001020 min_match_ = 0;
1021 max_match_ = 0;
1022 for (int i = 0; i < nodes->length(); i++) {
1023 RegExpTree* node = nodes->at(i);
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00001024 int node_min_match = node->min_match();
1025 min_match_ = IncreaseBy(min_match_, node_min_match);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001026 int node_max_match = node->max_match();
jkummerow@chromium.org212d9642012-05-11 15:02:09 +00001027 max_match_ = IncreaseBy(max_match_, node_max_match);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +00001028 }
1029}
1030
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001031
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001032CaseClause::CaseClause(Isolate* isolate,
1033 Expression* label,
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001034 ZoneList<Statement*>* statements,
1035 int pos)
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +00001036 : AstNode(pos),
1037 label_(label),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001038 statements_(statements),
danno@chromium.org41728482013-06-12 22:31:22 +00001039 compare_type_(Type::None(), isolate),
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001040 compare_id_(AstNode::GetNextId(isolate)),
1041 entry_id_(AstNode::GetNextId(isolate)) {
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001042}
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001043
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001044
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001045#define REGULAR_NODE(NodeType) \
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001046 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1047 increase_node_count(); \
1048 }
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001049#define DONT_OPTIMIZE_NODE(NodeType) \
1050 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1051 increase_node_count(); \
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +00001052 set_dont_optimize_reason(k##NodeType); \
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001053 add_flag(kDontInline); \
1054 add_flag(kDontSelfOptimize); \
1055 }
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001056#define DONT_SELFOPTIMIZE_NODE(NodeType) \
1057 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1058 increase_node_count(); \
1059 add_flag(kDontSelfOptimize); \
1060 }
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001061#define DONT_CACHE_NODE(NodeType) \
1062 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
1063 increase_node_count(); \
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +00001064 set_dont_optimize_reason(k##NodeType); \
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001065 add_flag(kDontInline); \
1066 add_flag(kDontSelfOptimize); \
1067 add_flag(kDontCache); \
1068 }
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001069
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001070REGULAR_NODE(VariableDeclaration)
1071REGULAR_NODE(FunctionDeclaration)
1072REGULAR_NODE(Block)
1073REGULAR_NODE(ExpressionStatement)
1074REGULAR_NODE(EmptyStatement)
1075REGULAR_NODE(IfStatement)
1076REGULAR_NODE(ContinueStatement)
1077REGULAR_NODE(BreakStatement)
1078REGULAR_NODE(ReturnStatement)
svenpanne@chromium.orgfb046332012-04-19 12:02:44 +00001079REGULAR_NODE(SwitchStatement)
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +00001080REGULAR_NODE(CaseClause)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001081REGULAR_NODE(Conditional)
1082REGULAR_NODE(Literal)
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001083REGULAR_NODE(ArrayLiteral)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001084REGULAR_NODE(ObjectLiteral)
yangguo@chromium.org9c741c82012-06-28 15:04:22 +00001085REGULAR_NODE(RegExpLiteral)
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001086REGULAR_NODE(FunctionLiteral)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001087REGULAR_NODE(Assignment)
1088REGULAR_NODE(Throw)
1089REGULAR_NODE(Property)
1090REGULAR_NODE(UnaryOperation)
1091REGULAR_NODE(CountOperation)
1092REGULAR_NODE(BinaryOperation)
1093REGULAR_NODE(CompareOperation)
1094REGULAR_NODE(ThisFunction)
1095REGULAR_NODE(Call)
1096REGULAR_NODE(CallNew)
1097// In theory, for VariableProxy we'd have to add:
1098// if (node->var()->IsLookupSlot()) add_flag(kDontInline);
1099// But node->var() is usually not bound yet at VariableProxy creation time, and
1100// LOOKUP variables only result from constructs that cannot be inlined anyway.
1101REGULAR_NODE(VariableProxy)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001102
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001103// We currently do not optimize any modules.
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001104DONT_OPTIMIZE_NODE(ModuleDeclaration)
1105DONT_OPTIMIZE_NODE(ImportDeclaration)
1106DONT_OPTIMIZE_NODE(ExportDeclaration)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001107DONT_OPTIMIZE_NODE(ModuleVariable)
1108DONT_OPTIMIZE_NODE(ModulePath)
1109DONT_OPTIMIZE_NODE(ModuleUrl)
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001110DONT_OPTIMIZE_NODE(ModuleStatement)
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00001111DONT_OPTIMIZE_NODE(Yield)
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001112DONT_OPTIMIZE_NODE(WithStatement)
1113DONT_OPTIMIZE_NODE(TryCatchStatement)
1114DONT_OPTIMIZE_NODE(TryFinallyStatement)
1115DONT_OPTIMIZE_NODE(DebuggerStatement)
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +00001116DONT_OPTIMIZE_NODE(NativeFunctionLiteral)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001117
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001118DONT_SELFOPTIMIZE_NODE(DoWhileStatement)
1119DONT_SELFOPTIMIZE_NODE(WhileStatement)
1120DONT_SELFOPTIMIZE_NODE(ForStatement)
1121DONT_SELFOPTIMIZE_NODE(ForInStatement)
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001122DONT_SELFOPTIMIZE_NODE(ForOfStatement)
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001123
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001124DONT_CACHE_NODE(ModuleLiteral)
1125
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001126void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
1127 increase_node_count();
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001128 if (node->is_jsruntime()) {
1129 // Don't try to inline JS runtime calls because we don't (currently) even
1130 // optimize them.
1131 add_flag(kDontInline);
1132 } else if (node->function()->intrinsic_type == Runtime::INLINE &&
jkummerow@chromium.org59297c72013-01-09 16:32:23 +00001133 (node->name()->IsOneByteEqualTo(
1134 STATIC_ASCII_VECTOR("_ArgumentsLength")) ||
1135 node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
svenpanne@chromium.orgb1df11d2012-02-08 10:26:21 +00001136 // Don't inline the %_ArgumentsLength or %_Arguments because their
1137 // implementation will not work. There is no stack frame to get them
1138 // from.
1139 add_flag(kDontInline);
1140 }
1141}
1142
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001143#undef REGULAR_NODE
1144#undef DONT_OPTIMIZE_NODE
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001145#undef DONT_SELFOPTIMIZE_NODE
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001146#undef DONT_CACHE_NODE
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00001147
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001148
1149Handle<String> Literal::ToString() {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001150 if (value_->IsString()) return Handle<String>::cast(value_);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001151 ASSERT(value_->IsNumber());
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001152 char arr[100];
1153 Vector<char> buffer(arr, ARRAY_SIZE(arr));
1154 const char* str;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001155 if (value_->IsSmi()) {
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001156 // Optimization only, the heap number case would subsume this.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001157 OS::SNPrintF(buffer, "%d", Smi::cast(*value_)->value());
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001158 str = arr;
1159 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001160 str = DoubleToCString(value_->Number(), buffer);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001161 }
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +00001162 return isolate_->factory()->NewStringFromAscii(CStrVector(str));
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001163}
1164
1165
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001166} } // namespace v8::internal