blob: c3fd9c0142c3e112b00739ed1d3b4589230485ad [file] [log] [blame]
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "typing.h"
29
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000030#include "parser.h" // for CompileTimeValue; TODO(rossberg): should move
31#include "scopes.h"
32
33namespace v8 {
34namespace internal {
35
36
37AstTyper::AstTyper(CompilationInfo* info)
38 : info_(info),
39 oracle_(
40 Handle<Code>(info->closure()->shared()->code()),
41 Handle<Context>(info->closure()->context()->native_context()),
42 info->isolate(),
danno@chromium.org59400602013-08-13 17:09:37 +000043 info->zone()),
44 store_(info->zone()) {
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000045 InitializeAstVisitor(info->isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000046}
47
48
danno@chromium.orgbee51992013-07-10 14:57:15 +000049#define RECURSE(call) \
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000050 do { \
danno@chromium.orgbee51992013-07-10 14:57:15 +000051 ASSERT(!visitor->HasStackOverflow()); \
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000052 call; \
53 if (visitor->HasStackOverflow()) return; \
54 } while (false)
55
danno@chromium.org41728482013-06-12 22:31:22 +000056void AstTyper::Run(CompilationInfo* info) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000057 AstTyper* visitor = new(info->zone()) AstTyper(info);
58 Scope* scope = info->scope();
59
60 // Handle implicit declaration of the function name in named function
61 // expressions before other declarations.
62 if (scope->is_function_scope() && scope->function() != NULL) {
danno@chromium.orgbee51992013-07-10 14:57:15 +000063 RECURSE(visitor->VisitVariableDeclaration(scope->function()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000064 }
danno@chromium.orgbee51992013-07-10 14:57:15 +000065 RECURSE(visitor->VisitDeclarations(scope->declarations()));
66 RECURSE(visitor->VisitStatements(info->function()->body()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000067}
68
danno@chromium.orgbee51992013-07-10 14:57:15 +000069#undef RECURSE
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000070
danno@chromium.orgbee51992013-07-10 14:57:15 +000071#define RECURSE(call) \
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000072 do { \
danno@chromium.orgbee51992013-07-10 14:57:15 +000073 ASSERT(!HasStackOverflow()); \
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000074 call; \
75 if (HasStackOverflow()) return; \
76 } while (false)
77
78
79void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000080 for (int i = 0; i < stmts->length(); ++i) {
81 Statement* stmt = stmts->at(i);
danno@chromium.orgbee51992013-07-10 14:57:15 +000082 RECURSE(Visit(stmt));
danno@chromium.org59400602013-08-13 17:09:37 +000083 if (stmt->IsJump()) break;
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000084 }
85}
86
87
88void AstTyper::VisitBlock(Block* stmt) {
danno@chromium.orgbee51992013-07-10 14:57:15 +000089 RECURSE(VisitStatements(stmt->statements()));
danno@chromium.org59400602013-08-13 17:09:37 +000090 if (stmt->labels() != NULL) {
91 store_.Forget(); // Control may transfer here via 'break l'.
92 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000093}
94
95
96void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
danno@chromium.orgbee51992013-07-10 14:57:15 +000097 RECURSE(Visit(stmt->expression()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000098}
99
100
101void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000102}
103
104
105void AstTyper::VisitIfStatement(IfStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000106 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000107 if (!stmt->condition()->ToBooleanIsTrue() &&
108 !stmt->condition()->ToBooleanIsFalse()) {
109 stmt->condition()->RecordToBooleanTypeFeedback(oracle());
110 }
danno@chromium.org59400602013-08-13 17:09:37 +0000111
112 RECURSE(Visit(stmt->condition()));
113 Effects then_effects = EnterEffects();
114 RECURSE(Visit(stmt->then_statement()));
115 ExitEffects();
116 Effects else_effects = EnterEffects();
117 RECURSE(Visit(stmt->else_statement()));
118 ExitEffects();
119 then_effects.Alt(else_effects);
120 store_.Seq(then_effects);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000121}
122
123
124void AstTyper::VisitContinueStatement(ContinueStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000125 // TODO(rossberg): is it worth having a non-termination effect?
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000126}
127
128
129void AstTyper::VisitBreakStatement(BreakStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000130 // TODO(rossberg): is it worth having a non-termination effect?
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000131}
132
133
134void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000135 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000136 // TODO(rossberg): we only need this for inlining into test contexts...
137 stmt->expression()->RecordToBooleanTypeFeedback(oracle());
danno@chromium.org59400602013-08-13 17:09:37 +0000138
139 RECURSE(Visit(stmt->expression()));
140 // TODO(rossberg): is it worth having a non-termination effect?
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000141}
142
143
144void AstTyper::VisitWithStatement(WithStatement* stmt) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000145 RECURSE(stmt->expression());
146 RECURSE(stmt->statement());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000147}
148
149
150void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000151 RECURSE(Visit(stmt->tag()));
danno@chromium.org59400602013-08-13 17:09:37 +0000152
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000153 ZoneList<CaseClause*>* clauses = stmt->cases();
154 SwitchStatement::SwitchType switch_type = stmt->switch_type();
danno@chromium.org59400602013-08-13 17:09:37 +0000155 Effects local_effects(zone());
156 bool complex_effects = false; // True for label effects or fall-through.
157
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000158 for (int i = 0; i < clauses->length(); ++i) {
159 CaseClause* clause = clauses->at(i);
danno@chromium.org59400602013-08-13 17:09:37 +0000160 Effects clause_effects = EnterEffects();
161
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000162 if (!clause->is_default()) {
163 Expression* label = clause->label();
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000164 SwitchStatement::SwitchType label_switch_type =
165 label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH :
166 label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH :
167 SwitchStatement::GENERIC_SWITCH;
168 if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
169 switch_type = label_switch_type;
170 else if (switch_type != label_switch_type)
171 switch_type = SwitchStatement::GENERIC_SWITCH;
danno@chromium.org59400602013-08-13 17:09:37 +0000172
173 RECURSE(Visit(label));
174 if (!clause_effects.IsEmpty()) complex_effects = true;
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000175 }
danno@chromium.org59400602013-08-13 17:09:37 +0000176
177 ZoneList<Statement*>* stmts = clause->statements();
178 RECURSE(VisitStatements(stmts));
179 ExitEffects();
180 if (stmts->is_empty() || stmts->last()->IsJump()) {
181 local_effects.Alt(clause_effects);
182 } else {
183 complex_effects = true;
184 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000185 }
danno@chromium.org59400602013-08-13 17:09:37 +0000186
187 if (complex_effects) {
188 store_.Forget(); // Reached this in unknown state.
189 } else {
190 store_.Seq(local_effects);
191 }
192
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000193 if (switch_type == SwitchStatement::UNKNOWN_SWITCH)
194 switch_type = SwitchStatement::GENERIC_SWITCH;
195 stmt->set_switch_type(switch_type);
196
danno@chromium.org59400602013-08-13 17:09:37 +0000197 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000198 // TODO(rossberg): can we eliminate this special case and extra loop?
199 if (switch_type == SwitchStatement::SMI_SWITCH) {
200 for (int i = 0; i < clauses->length(); ++i) {
201 CaseClause* clause = clauses->at(i);
202 if (!clause->is_default())
203 clause->RecordTypeFeedback(oracle());
204 }
205 }
206}
207
208
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000209void AstTyper::VisitCaseClause(CaseClause* clause) {
210 UNREACHABLE();
211}
212
213
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000214void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000215 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000216 if (!stmt->cond()->ToBooleanIsTrue()) {
217 stmt->cond()->RecordToBooleanTypeFeedback(oracle());
218 }
danno@chromium.org59400602013-08-13 17:09:37 +0000219
220 // TODO(rossberg): refine the unconditional Forget (here and elsewhere) by
221 // computing the set of variables assigned in only some of the origins of the
222 // control transfer (such as the loop body here).
223 store_.Forget(); // Control may transfer here via looping or 'continue'.
224 RECURSE(Visit(stmt->body()));
225 RECURSE(Visit(stmt->cond()));
226 store_.Forget(); // Control may transfer here via 'break'.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000227}
228
229
230void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000231 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000232 if (!stmt->cond()->ToBooleanIsTrue()) {
233 stmt->cond()->RecordToBooleanTypeFeedback(oracle());
234 }
danno@chromium.org59400602013-08-13 17:09:37 +0000235
236 store_.Forget(); // Control may transfer here via looping or 'continue'.
237 RECURSE(Visit(stmt->cond()));
238 RECURSE(Visit(stmt->body()));
239 store_.Forget(); // Control may transfer here via termination or 'break'.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000240}
241
242
243void AstTyper::VisitForStatement(ForStatement* stmt) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000244 if (stmt->init() != NULL) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000245 RECURSE(Visit(stmt->init()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000246 }
danno@chromium.org59400602013-08-13 17:09:37 +0000247 store_.Forget(); // Control may transfer here via looping.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000248 if (stmt->cond() != NULL) {
danno@chromium.org59400602013-08-13 17:09:37 +0000249 // Collect type feedback.
danno@chromium.org93ac1662013-08-07 09:48:48 +0000250 stmt->cond()->RecordToBooleanTypeFeedback(oracle());
danno@chromium.org59400602013-08-13 17:09:37 +0000251
252 RECURSE(Visit(stmt->cond()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000253 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000254 RECURSE(Visit(stmt->body()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000255 if (stmt->next() != NULL) {
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000256 store_.Forget(); // Control may transfer here via 'continue'.
danno@chromium.orgbee51992013-07-10 14:57:15 +0000257 RECURSE(Visit(stmt->next()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000258 }
danno@chromium.org59400602013-08-13 17:09:37 +0000259 store_.Forget(); // Control may transfer here via termination or 'break'.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000260}
261
262
263void AstTyper::VisitForInStatement(ForInStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000264 // Collect type feedback.
danno@chromium.org93ac1662013-08-07 09:48:48 +0000265 stmt->RecordTypeFeedback(oracle());
danno@chromium.org59400602013-08-13 17:09:37 +0000266
267 RECURSE(Visit(stmt->enumerable()));
268 store_.Forget(); // Control may transfer here via looping or 'continue'.
269 RECURSE(Visit(stmt->body()));
270 store_.Forget(); // Control may transfer here via 'break'.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000271}
272
273
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000274void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000275 RECURSE(Visit(stmt->iterable()));
danno@chromium.org59400602013-08-13 17:09:37 +0000276 store_.Forget(); // Control may transfer here via looping or 'continue'.
danno@chromium.orgbee51992013-07-10 14:57:15 +0000277 RECURSE(Visit(stmt->body()));
danno@chromium.org59400602013-08-13 17:09:37 +0000278 store_.Forget(); // Control may transfer here via 'break'.
danno@chromium.org1fd77d52013-06-07 16:01:45 +0000279}
280
281
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000282void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000283 Effects try_effects = EnterEffects();
danno@chromium.orgbee51992013-07-10 14:57:15 +0000284 RECURSE(Visit(stmt->try_block()));
danno@chromium.org59400602013-08-13 17:09:37 +0000285 ExitEffects();
286 Effects catch_effects = EnterEffects();
287 store_.Forget(); // Control may transfer here via 'throw'.
danno@chromium.orgbee51992013-07-10 14:57:15 +0000288 RECURSE(Visit(stmt->catch_block()));
danno@chromium.org59400602013-08-13 17:09:37 +0000289 ExitEffects();
290 try_effects.Alt(catch_effects);
291 store_.Seq(try_effects);
292 // At this point, only variables that were reassigned in the catch block are
293 // still remembered.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000294}
295
296
297void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000298 RECURSE(Visit(stmt->try_block()));
danno@chromium.org59400602013-08-13 17:09:37 +0000299 store_.Forget(); // Control may transfer here via 'throw'.
danno@chromium.orgbee51992013-07-10 14:57:15 +0000300 RECURSE(Visit(stmt->finally_block()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000301}
302
303
304void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
danno@chromium.org59400602013-08-13 17:09:37 +0000305 store_.Forget(); // May do whatever.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000306}
307
308
309void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000310}
311
312
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +0000313void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000314}
315
316
317void AstTyper::VisitConditional(Conditional* expr) {
danno@chromium.org59400602013-08-13 17:09:37 +0000318 // Collect type feedback.
danno@chromium.org93ac1662013-08-07 09:48:48 +0000319 expr->condition()->RecordToBooleanTypeFeedback(oracle());
dslomov@chromium.org6b37f822013-08-07 09:20:40 +0000320
danno@chromium.org59400602013-08-13 17:09:37 +0000321 RECURSE(Visit(expr->condition()));
322 Effects then_effects = EnterEffects();
323 RECURSE(Visit(expr->then_expression()));
324 ExitEffects();
325 Effects else_effects = EnterEffects();
326 RECURSE(Visit(expr->else_expression()));
327 ExitEffects();
328 then_effects.Alt(else_effects);
329 store_.Seq(then_effects);
330
danno@chromium.org169691d2013-07-15 08:01:13 +0000331 NarrowType(expr, Bounds::Either(
332 expr->then_expression()->bounds(),
333 expr->else_expression()->bounds(), isolate_));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000334}
335
336
337void AstTyper::VisitVariableProxy(VariableProxy* expr) {
danno@chromium.org59400602013-08-13 17:09:37 +0000338 Variable* var = expr->var();
339 if (var->IsStackAllocated()) {
340 NarrowType(expr, store_.LookupBounds(variable_index(var)));
341 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000342}
343
344
345void AstTyper::VisitLiteral(Literal* expr) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000346 Type* type = Type::Constant(expr->value(), isolate_);
danno@chromium.org169691d2013-07-15 08:01:13 +0000347 NarrowType(expr, Bounds(type, isolate_));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000348}
349
350
351void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
danno@chromium.org169691d2013-07-15 08:01:13 +0000352 NarrowType(expr, Bounds(Type::RegExp(), isolate_));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000353}
354
355
356void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000357 ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
358 for (int i = 0; i < properties->length(); ++i) {
359 ObjectLiteral::Property* prop = properties->at(i);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000360
danno@chromium.org59400602013-08-13 17:09:37 +0000361 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000362 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
363 !CompileTimeValue::IsCompileTimeValue(prop->value())) ||
364 prop->kind() == ObjectLiteral::Property::COMPUTED) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000365 if (prop->key()->value()->IsInternalizedString() && prop->emit_store()) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000366 prop->RecordTypeFeedback(oracle());
danno@chromium.orgbee51992013-07-10 14:57:15 +0000367 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000368 }
danno@chromium.org59400602013-08-13 17:09:37 +0000369
370 RECURSE(Visit(prop->value()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000371 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000372
danno@chromium.org169691d2013-07-15 08:01:13 +0000373 NarrowType(expr, Bounds(Type::Object(), isolate_));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000374}
375
376
377void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000378 ZoneList<Expression*>* values = expr->values();
379 for (int i = 0; i < values->length(); ++i) {
380 Expression* value = values->at(i);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000381 RECURSE(Visit(value));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000382 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000383
danno@chromium.org169691d2013-07-15 08:01:13 +0000384 NarrowType(expr, Bounds(Type::Array(), isolate_));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000385}
386
387
388void AstTyper::VisitAssignment(Assignment* expr) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000389 // TODO(rossberg): Can we clean this up?
390 if (expr->is_compound()) {
danno@chromium.org59400602013-08-13 17:09:37 +0000391 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000392 Expression* target = expr->target();
393 Property* prop = target->AsProperty();
394 if (prop != NULL) {
395 prop->RecordTypeFeedback(oracle(), zone());
danno@chromium.org93ac1662013-08-07 09:48:48 +0000396 expr->RecordTypeFeedback(oracle(), zone());
397 }
398
danno@chromium.org59400602013-08-13 17:09:37 +0000399 RECURSE(Visit(expr->binary_operation()));
400
401 NarrowType(expr, expr->binary_operation()->bounds());
402 } else {
403 // Collect type feedback.
404 if (expr->target()->IsProperty()) {
405 expr->RecordTypeFeedback(oracle(), zone());
406 }
407
408 RECURSE(Visit(expr->target()));
409 RECURSE(Visit(expr->value()));
410
danno@chromium.org169691d2013-07-15 08:01:13 +0000411 NarrowType(expr, expr->value()->bounds());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000412 }
danno@chromium.org59400602013-08-13 17:09:37 +0000413
414 VariableProxy* proxy = expr->target()->AsVariableProxy();
415 if (proxy != NULL && proxy->var()->IsStackAllocated()) {
416 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
417 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000418}
419
420
421void AstTyper::VisitYield(Yield* expr) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000422 RECURSE(Visit(expr->generator_object()));
423 RECURSE(Visit(expr->expression()));
424
danno@chromium.org59400602013-08-13 17:09:37 +0000425 // We don't know anything about the result type.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000426}
427
428
429void AstTyper::VisitThrow(Throw* expr) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000430 RECURSE(Visit(expr->exception()));
danno@chromium.org59400602013-08-13 17:09:37 +0000431 // TODO(rossberg): is it worth having a non-termination effect?
danno@chromium.orgbee51992013-07-10 14:57:15 +0000432
danno@chromium.org169691d2013-07-15 08:01:13 +0000433 NarrowType(expr, Bounds(Type::None(), isolate_));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000434}
435
436
437void AstTyper::VisitProperty(Property* expr) {
danno@chromium.org59400602013-08-13 17:09:37 +0000438 // Collect type feedback.
439 expr->RecordTypeFeedback(oracle(), zone());
440
danno@chromium.orgbee51992013-07-10 14:57:15 +0000441 RECURSE(Visit(expr->obj()));
442 RECURSE(Visit(expr->key()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000443
danno@chromium.org59400602013-08-13 17:09:37 +0000444 // We don't know anything about the result type.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000445}
446
447
448void AstTyper::VisitCall(Call* expr) {
danno@chromium.org59400602013-08-13 17:09:37 +0000449 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000450 Expression* callee = expr->expression();
451 Property* prop = callee->AsProperty();
452 if (prop != NULL) {
453 if (prop->key()->IsPropertyName())
454 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD);
455 } else {
456 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
457 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000458
dslomov@chromium.org6b37f822013-08-07 09:20:40 +0000459 RECURSE(Visit(expr->expression()));
460 ZoneList<Expression*>* args = expr->arguments();
461 for (int i = 0; i < args->length(); ++i) {
462 Expression* arg = args->at(i);
463 RECURSE(Visit(arg));
464 }
465
danno@chromium.org59400602013-08-13 17:09:37 +0000466 VariableProxy* proxy = expr->expression()->AsVariableProxy();
467 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
468 store_.Forget(); // Eval could do whatever to local variables.
469 }
470
471 // We don't know anything about the result type.
472}
473
474
475void AstTyper::VisitCallNew(CallNew* expr) {
476 // Collect type feedback.
danno@chromium.org93ac1662013-08-07 09:48:48 +0000477 expr->RecordTypeFeedback(oracle());
478
danno@chromium.org59400602013-08-13 17:09:37 +0000479 RECURSE(Visit(expr->expression()));
480 ZoneList<Expression*>* args = expr->arguments();
481 for (int i = 0; i < args->length(); ++i) {
482 Expression* arg = args->at(i);
483 RECURSE(Visit(arg));
484 }
485
486 // We don't know anything about the result type.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000487}
488
489
490void AstTyper::VisitCallRuntime(CallRuntime* expr) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000491 ZoneList<Expression*>* args = expr->arguments();
492 for (int i = 0; i < args->length(); ++i) {
493 Expression* arg = args->at(i);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000494 RECURSE(Visit(arg));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000495 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000496
danno@chromium.org59400602013-08-13 17:09:37 +0000497 // We don't know anything about the result type.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000498}
499
500
501void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000502 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000503 if (expr->op() == Token::NOT) {
504 // TODO(rossberg): only do in test or value context.
505 expr->expression()->RecordToBooleanTypeFeedback(oracle());
506 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000507
danno@chromium.org59400602013-08-13 17:09:37 +0000508 RECURSE(Visit(expr->expression()));
509
danno@chromium.orgbee51992013-07-10 14:57:15 +0000510 switch (expr->op()) {
511 case Token::NOT:
512 case Token::DELETE:
danno@chromium.org169691d2013-07-15 08:01:13 +0000513 NarrowType(expr, Bounds(Type::Boolean(), isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000514 break;
515 case Token::VOID:
danno@chromium.org169691d2013-07-15 08:01:13 +0000516 NarrowType(expr, Bounds(Type::Undefined(), isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000517 break;
danno@chromium.orgbee51992013-07-10 14:57:15 +0000518 case Token::TYPEOF:
danno@chromium.org169691d2013-07-15 08:01:13 +0000519 NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000520 break;
521 default:
522 UNREACHABLE();
523 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000524}
525
526
527void AstTyper::VisitCountOperation(CountOperation* expr) {
danno@chromium.org59400602013-08-13 17:09:37 +0000528 // Collect type feedback.
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000529 expr->RecordTypeFeedback(oracle(), zone());
530 Property* prop = expr->expression()->AsProperty();
531 if (prop != NULL) {
532 prop->RecordTypeFeedback(oracle(), zone());
533 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000534
danno@chromium.org59400602013-08-13 17:09:37 +0000535 RECURSE(Visit(expr->expression()));
536
danno@chromium.org169691d2013-07-15 08:01:13 +0000537 NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
danno@chromium.org59400602013-08-13 17:09:37 +0000538
539 VariableProxy* proxy = expr->expression()->AsVariableProxy();
540 if (proxy != NULL && proxy->var()->IsStackAllocated()) {
541 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds()));
542 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000543}
544
545
546void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000547 // Collect type feedback.
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000548 Handle<Type> type, left_type, right_type;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000549 Maybe<int> fixed_right_arg;
550 oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
jkummerow@chromium.org25b0e212013-10-04 15:38:52 +0000551 &left_type, &right_type, &type, &fixed_right_arg, expr->op());
danno@chromium.org169691d2013-07-15 08:01:13 +0000552 NarrowLowerType(expr, type);
553 NarrowLowerType(expr->left(), left_type);
554 NarrowLowerType(expr->right(), right_type);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000555 expr->set_fixed_right_arg(fixed_right_arg);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000556 if (expr->op() == Token::OR || expr->op() == Token::AND) {
557 expr->left()->RecordToBooleanTypeFeedback(oracle());
558 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000559
560 switch (expr->op()) {
561 case Token::COMMA:
danno@chromium.org59400602013-08-13 17:09:37 +0000562 RECURSE(Visit(expr->left()));
563 RECURSE(Visit(expr->right()));
danno@chromium.org169691d2013-07-15 08:01:13 +0000564 NarrowType(expr, expr->right()->bounds());
danno@chromium.orgbee51992013-07-10 14:57:15 +0000565 break;
566 case Token::OR:
danno@chromium.org59400602013-08-13 17:09:37 +0000567 case Token::AND: {
568 Effects left_effects = EnterEffects();
569 RECURSE(Visit(expr->left()));
570 ExitEffects();
571 Effects right_effects = EnterEffects();
572 RECURSE(Visit(expr->right()));
573 ExitEffects();
574 left_effects.Alt(right_effects);
575 store_.Seq(left_effects);
576
danno@chromium.org169691d2013-07-15 08:01:13 +0000577 NarrowType(expr, Bounds::Either(
578 expr->left()->bounds(), expr->right()->bounds(), isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000579 break;
danno@chromium.org59400602013-08-13 17:09:37 +0000580 }
danno@chromium.orgbee51992013-07-10 14:57:15 +0000581 case Token::BIT_OR:
582 case Token::BIT_AND: {
danno@chromium.org59400602013-08-13 17:09:37 +0000583 RECURSE(Visit(expr->left()));
584 RECURSE(Visit(expr->right()));
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000585 Handle<Type> upper(
586 Type::Union(
587 expr->left()->bounds().upper, expr->right()->bounds().upper),
588 isolate_);
589 if (!upper->Is(Type::Signed32()))
590 upper = handle(Type::Signed32(), isolate_);
591 Handle<Type> lower(Type::Intersect(
592 handle(Type::Smi(), isolate_), upper), isolate_);
593 NarrowType(expr, Bounds(lower, upper));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000594 break;
595 }
596 case Token::BIT_XOR:
597 case Token::SHL:
598 case Token::SAR:
danno@chromium.org59400602013-08-13 17:09:37 +0000599 RECURSE(Visit(expr->left()));
600 RECURSE(Visit(expr->right()));
danno@chromium.org169691d2013-07-15 08:01:13 +0000601 NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000602 break;
603 case Token::SHR:
danno@chromium.org59400602013-08-13 17:09:37 +0000604 RECURSE(Visit(expr->left()));
605 RECURSE(Visit(expr->right()));
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000606 // TODO(rossberg): we could use an UnsignedSmi as lower bound here...
607 NarrowType(expr, Bounds(Type::Unsigned32(), isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000608 break;
609 case Token::ADD: {
danno@chromium.org59400602013-08-13 17:09:37 +0000610 RECURSE(Visit(expr->left()));
611 RECURSE(Visit(expr->right()));
danno@chromium.org169691d2013-07-15 08:01:13 +0000612 Bounds l = expr->left()->bounds();
613 Bounds r = expr->right()->bounds();
614 Type* lower =
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000615 l.lower->Is(Type::None()) || r.lower->Is(Type::None()) ?
616 Type::None() :
danno@chromium.org169691d2013-07-15 08:01:13 +0000617 l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000618 Type::String() :
619 l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
620 Type::Smi() : Type::None();
danno@chromium.org169691d2013-07-15 08:01:13 +0000621 Type* upper =
danno@chromium.org169691d2013-07-15 08:01:13 +0000622 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +0000623 Type::String() :
624 l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
625 Type::Number() : Type::NumberOrString();
danno@chromium.org169691d2013-07-15 08:01:13 +0000626 NarrowType(expr, Bounds(lower, upper, isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000627 break;
628 }
629 case Token::SUB:
630 case Token::MUL:
631 case Token::DIV:
632 case Token::MOD:
danno@chromium.org59400602013-08-13 17:09:37 +0000633 RECURSE(Visit(expr->left()));
634 RECURSE(Visit(expr->right()));
danno@chromium.org169691d2013-07-15 08:01:13 +0000635 NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
danno@chromium.orgbee51992013-07-10 14:57:15 +0000636 break;
637 default:
638 UNREACHABLE();
639 }
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000640}
641
642
643void AstTyper::VisitCompareOperation(CompareOperation* expr) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000644 // Collect type feedback.
645 Handle<Type> left_type, right_type, combined_type;
646 oracle()->CompareType(expr->CompareOperationFeedbackId(),
647 &left_type, &right_type, &combined_type);
danno@chromium.org169691d2013-07-15 08:01:13 +0000648 NarrowLowerType(expr->left(), left_type);
649 NarrowLowerType(expr->right(), right_type);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000650 expr->set_combined_type(combined_type);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000651
danno@chromium.org59400602013-08-13 17:09:37 +0000652 RECURSE(Visit(expr->left()));
653 RECURSE(Visit(expr->right()));
654
danno@chromium.org169691d2013-07-15 08:01:13 +0000655 NarrowType(expr, Bounds(Type::Boolean(), isolate_));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000656}
657
658
659void AstTyper::VisitThisFunction(ThisFunction* expr) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000660}
661
662
663void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000664 for (int i = 0; i < decls->length(); ++i) {
665 Declaration* decl = decls->at(i);
danno@chromium.orgbee51992013-07-10 14:57:15 +0000666 RECURSE(Visit(decl));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000667 }
668}
669
670
671void AstTyper::VisitVariableDeclaration(VariableDeclaration* declaration) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000672}
673
674
675void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000676 RECURSE(Visit(declaration->fun()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000677}
678
679
680void AstTyper::VisitModuleDeclaration(ModuleDeclaration* declaration) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000681 RECURSE(Visit(declaration->module()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000682}
683
684
685void AstTyper::VisitImportDeclaration(ImportDeclaration* declaration) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000686 RECURSE(Visit(declaration->module()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000687}
688
689
690void AstTyper::VisitExportDeclaration(ExportDeclaration* declaration) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000691}
692
693
694void AstTyper::VisitModuleLiteral(ModuleLiteral* module) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000695 RECURSE(Visit(module->body()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000696}
697
698
699void AstTyper::VisitModuleVariable(ModuleVariable* module) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000700}
701
702
703void AstTyper::VisitModulePath(ModulePath* module) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000704 RECURSE(Visit(module->module()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000705}
706
707
708void AstTyper::VisitModuleUrl(ModuleUrl* module) {
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000709}
710
711
712void AstTyper::VisitModuleStatement(ModuleStatement* stmt) {
danno@chromium.orgbee51992013-07-10 14:57:15 +0000713 RECURSE(Visit(stmt->body()));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +0000714}
715
716
717} } // namespace v8::internal