• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/typing-asm.h"
6 
7 #include <limits>
8 
9 #include "src/v8.h"
10 
11 #include "src/ast/ast.h"
12 #include "src/ast/scopes.h"
13 #include "src/codegen.h"
14 #include "src/type-cache.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 #define FAIL(node, msg)                                        \
20   do {                                                         \
21     valid_ = false;                                            \
22     int line = node->position() == RelocInfo::kNoPosition      \
23                    ? -1                                        \
24                    : script_->GetLineNumber(node->position()); \
25     base::OS::SNPrintF(error_message_, sizeof(error_message_), \
26                        "asm: line %d: %s\n", line + 1, msg);   \
27     return;                                                    \
28   } while (false)
29 
30 
31 #define RECURSE(call)               \
32   do {                              \
33     DCHECK(!HasStackOverflow());    \
34     call;                           \
35     if (HasStackOverflow()) return; \
36     if (!valid_) return;            \
37   } while (false)
38 
39 
AsmTyper(Isolate * isolate,Zone * zone,Script * script,FunctionLiteral * root)40 AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
41                    FunctionLiteral* root)
42     : zone_(zone),
43       isolate_(isolate),
44       script_(script),
45       root_(root),
46       valid_(true),
47       allow_simd_(false),
48       property_info_(NULL),
49       intish_(0),
50       stdlib_types_(zone),
51       stdlib_heap_types_(zone),
52       stdlib_math_types_(zone),
53 #define V(NAME, Name, name, lane_count, lane_type) \
54   stdlib_simd_##name##_types_(zone),
55       SIMD128_TYPES(V)
56 #undef V
57           global_variable_type_(HashMap::PointersMatch,
58                                 ZoneHashMap::kDefaultHashMapCapacity,
59                                 ZoneAllocationPolicy(zone)),
60       local_variable_type_(HashMap::PointersMatch,
61                            ZoneHashMap::kDefaultHashMapCapacity,
62                            ZoneAllocationPolicy(zone)),
63       in_function_(false),
64       building_function_tables_(false),
65       cache_(TypeCache::Get()) {
66   InitializeAstVisitor(isolate);
67   InitializeStdlib();
68 }
69 
70 
Validate()71 bool AsmTyper::Validate() {
72   VisitAsmModule(root_);
73   return valid_ && !HasStackOverflow();
74 }
75 
76 
VisitAsmModule(FunctionLiteral * fun)77 void AsmTyper::VisitAsmModule(FunctionLiteral* fun) {
78   Scope* scope = fun->scope();
79   if (!scope->is_function_scope()) FAIL(fun, "not at function scope");
80 
81   ExpressionStatement* use_asm = fun->body()->first()->AsExpressionStatement();
82   if (use_asm == NULL) FAIL(fun, "missing \"use asm\"");
83   Literal* use_asm_literal = use_asm->expression()->AsLiteral();
84   if (use_asm_literal == NULL) FAIL(fun, "missing \"use asm\"");
85   if (!use_asm_literal->raw_value()->AsString()->IsOneByteEqualTo("use asm"))
86     FAIL(fun, "missing \"use asm\"");
87 
88   // Module parameters.
89   for (int i = 0; i < scope->num_parameters(); ++i) {
90     Variable* param = scope->parameter(i);
91     DCHECK(GetType(param) == NULL);
92     SetType(param, Type::None(zone()));
93   }
94 
95   ZoneList<Declaration*>* decls = scope->declarations();
96 
97   // Set all globals to type Any.
98   VariableDeclaration* decl = scope->function();
99   if (decl != NULL) SetType(decl->proxy()->var(), Type::None());
100   RECURSE(VisitDeclarations(scope->declarations()));
101 
102   // Validate global variables.
103   RECURSE(VisitStatements(fun->body()));
104 
105   // Validate function annotations.
106   for (int i = 0; i < decls->length(); ++i) {
107     FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
108     if (decl != NULL) {
109       RECURSE(VisitFunctionAnnotation(decl->fun()));
110       Variable* var = decl->proxy()->var();
111       if (property_info_ != NULL) {
112         SetVariableInfo(var, property_info_);
113         property_info_ = NULL;
114       }
115       SetType(var, computed_type_);
116       DCHECK(GetType(var) != NULL);
117     }
118   }
119 
120   // Build function tables.
121   building_function_tables_ = true;
122   RECURSE(VisitStatements(fun->body()));
123   building_function_tables_ = false;
124 
125   // Validate function bodies.
126   for (int i = 0; i < decls->length(); ++i) {
127     FunctionDeclaration* decl = decls->at(i)->AsFunctionDeclaration();
128     if (decl != NULL) {
129       RECURSE(
130           VisitWithExpectation(decl->fun(), Type::Any(zone()), "UNREACHABLE"));
131       if (!computed_type_->IsFunction()) {
132         FAIL(decl->fun(), "function literal expected to be a function");
133       }
134     }
135   }
136 
137   // Validate exports.
138   ReturnStatement* stmt = fun->body()->last()->AsReturnStatement();
139   if (stmt == nullptr) {
140     FAIL(fun->body()->last(), "last statement in module is not a return");
141   }
142   RECURSE(VisitWithExpectation(stmt->expression(), Type::Object(),
143                                "expected object export"));
144 }
145 
146 
VisitVariableDeclaration(VariableDeclaration * decl)147 void AsmTyper::VisitVariableDeclaration(VariableDeclaration* decl) {
148   Variable* var = decl->proxy()->var();
149   if (var->location() != VariableLocation::PARAMETER) {
150     if (GetType(var) == NULL) {
151       SetType(var, Type::Any(zone()));
152     } else {
153       DCHECK(!GetType(var)->IsFunction());
154     }
155   }
156   DCHECK(GetType(var) != NULL);
157   intish_ = 0;
158 }
159 
160 
VisitFunctionDeclaration(FunctionDeclaration * decl)161 void AsmTyper::VisitFunctionDeclaration(FunctionDeclaration* decl) {
162   if (in_function_) {
163     FAIL(decl, "function declared inside another");
164   }
165   // Set function type so global references to functions have some type
166   // (so they can give a more useful error).
167   Variable* var = decl->proxy()->var();
168   SetType(var, Type::Function(zone()));
169 }
170 
171 
VisitFunctionAnnotation(FunctionLiteral * fun)172 void AsmTyper::VisitFunctionAnnotation(FunctionLiteral* fun) {
173   // Extract result type.
174   ZoneList<Statement*>* body = fun->body();
175   Type* result_type = Type::Undefined(zone());
176   if (body->length() > 0) {
177     ReturnStatement* stmt = body->last()->AsReturnStatement();
178     if (stmt != NULL) {
179       Literal* literal = stmt->expression()->AsLiteral();
180       Type* old_expected = expected_type_;
181       expected_type_ = Type::Any();
182       if (literal) {
183         RECURSE(VisitLiteral(literal, true));
184       } else {
185         RECURSE(VisitExpressionAnnotation(stmt->expression(), NULL, true));
186       }
187       expected_type_ = old_expected;
188       result_type = computed_type_;
189     }
190   }
191   Type::FunctionType* type =
192       Type::Function(result_type, Type::Any(), fun->parameter_count(), zone())
193           ->AsFunction();
194 
195   // Extract parameter types.
196   bool good = true;
197   for (int i = 0; i < fun->parameter_count(); ++i) {
198     good = false;
199     if (i >= body->length()) break;
200     ExpressionStatement* stmt = body->at(i)->AsExpressionStatement();
201     if (stmt == NULL) break;
202     Assignment* expr = stmt->expression()->AsAssignment();
203     if (expr == NULL || expr->is_compound()) break;
204     VariableProxy* proxy = expr->target()->AsVariableProxy();
205     if (proxy == NULL) break;
206     Variable* var = proxy->var();
207     if (var->location() != VariableLocation::PARAMETER || var->index() != i)
208       break;
209     RECURSE(VisitExpressionAnnotation(expr->value(), var, false));
210     if (property_info_ != NULL) {
211       SetVariableInfo(var, property_info_);
212       property_info_ = NULL;
213     }
214     SetType(var, computed_type_);
215     type->InitParameter(i, computed_type_);
216     good = true;
217   }
218   if (!good) FAIL(fun, "missing parameter type annotations");
219 
220   SetResult(fun, type);
221 }
222 
223 
VisitExpressionAnnotation(Expression * expr,Variable * var,bool is_return)224 void AsmTyper::VisitExpressionAnnotation(Expression* expr, Variable* var,
225                                          bool is_return) {
226   // Normal +x or x|0 annotations.
227   BinaryOperation* bin = expr->AsBinaryOperation();
228   if (bin != NULL) {
229     if (var != NULL) {
230       VariableProxy* proxy = bin->left()->AsVariableProxy();
231       if (proxy == NULL) {
232         FAIL(bin->left(), "expected variable for type annotation");
233       }
234       if (proxy->var() != var) {
235         FAIL(proxy, "annotation source doesn't match destination");
236       }
237     }
238     Literal* right = bin->right()->AsLiteral();
239     if (right != NULL) {
240       switch (bin->op()) {
241         case Token::MUL:  // We encode +x as x*1.0
242           if (right->raw_value()->ContainsDot() &&
243               right->raw_value()->AsNumber() == 1.0) {
244             SetResult(expr, cache_.kAsmDouble);
245             return;
246           }
247           break;
248         case Token::BIT_OR:
249           if (!right->raw_value()->ContainsDot() &&
250               right->raw_value()->AsNumber() == 0.0) {
251             if (is_return) {
252               SetResult(expr, cache_.kAsmSigned);
253             } else {
254               SetResult(expr, cache_.kAsmInt);
255             }
256             return;
257           }
258           break;
259         default:
260           break;
261       }
262     }
263     FAIL(expr, "invalid type annotation on binary op");
264   }
265 
266   // Numbers or the undefined literal (for empty returns).
267   if (expr->IsLiteral()) {
268     RECURSE(VisitWithExpectation(expr, Type::Any(), "invalid literal"));
269     return;
270   }
271 
272   Call* call = expr->AsCall();
273   if (call != NULL) {
274     VariableProxy* proxy = call->expression()->AsVariableProxy();
275     if (proxy != NULL) {
276       VariableInfo* info = GetVariableInfo(proxy->var(), false);
277       if (!info ||
278           (!info->is_check_function && !info->is_constructor_function)) {
279         if (allow_simd_) {
280           FAIL(call->expression(),
281                "only fround/SIMD.checks allowed on expression annotations");
282         } else {
283           FAIL(call->expression(),
284                "only fround allowed on expression annotations");
285         }
286       }
287       Type* type = info->type;
288       DCHECK(type->IsFunction());
289       if (info->is_check_function) {
290         DCHECK(type->AsFunction()->Arity() == 1);
291       }
292       if (call->arguments()->length() != type->AsFunction()->Arity()) {
293         FAIL(call, "invalid argument count calling function");
294       }
295       SetResult(expr, type->AsFunction()->Result());
296       return;
297     }
298   }
299 
300   FAIL(expr, "invalid type annotation");
301 }
302 
303 
VisitStatements(ZoneList<Statement * > * stmts)304 void AsmTyper::VisitStatements(ZoneList<Statement*>* stmts) {
305   for (int i = 0; i < stmts->length(); ++i) {
306     Statement* stmt = stmts->at(i);
307     RECURSE(Visit(stmt));
308   }
309 }
310 
311 
VisitBlock(Block * stmt)312 void AsmTyper::VisitBlock(Block* stmt) {
313   RECURSE(VisitStatements(stmt->statements()));
314 }
315 
316 
VisitExpressionStatement(ExpressionStatement * stmt)317 void AsmTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
318   RECURSE(VisitWithExpectation(stmt->expression(), Type::Any(),
319                                "expression statement expected to be any"));
320 }
321 
322 
VisitEmptyStatement(EmptyStatement * stmt)323 void AsmTyper::VisitEmptyStatement(EmptyStatement* stmt) {}
324 
325 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * stmt)326 void AsmTyper::VisitSloppyBlockFunctionStatement(
327     SloppyBlockFunctionStatement* stmt) {
328   Visit(stmt->statement());
329 }
330 
331 
VisitEmptyParentheses(EmptyParentheses * expr)332 void AsmTyper::VisitEmptyParentheses(EmptyParentheses* expr) { UNREACHABLE(); }
333 
334 
VisitIfStatement(IfStatement * stmt)335 void AsmTyper::VisitIfStatement(IfStatement* stmt) {
336   if (!in_function_) {
337     FAIL(stmt, "if statement inside module body");
338   }
339   RECURSE(VisitWithExpectation(stmt->condition(), cache_.kAsmSigned,
340                                "if condition expected to be integer"));
341   RECURSE(Visit(stmt->then_statement()));
342   RECURSE(Visit(stmt->else_statement()));
343 }
344 
345 
VisitContinueStatement(ContinueStatement * stmt)346 void AsmTyper::VisitContinueStatement(ContinueStatement* stmt) {
347   if (!in_function_) {
348     FAIL(stmt, "continue statement inside module body");
349   }
350 }
351 
352 
VisitBreakStatement(BreakStatement * stmt)353 void AsmTyper::VisitBreakStatement(BreakStatement* stmt) {
354   if (!in_function_) {
355     FAIL(stmt, "continue statement inside module body");
356   }
357 }
358 
359 
VisitReturnStatement(ReturnStatement * stmt)360 void AsmTyper::VisitReturnStatement(ReturnStatement* stmt) {
361   // Handle module return statement in VisitAsmModule.
362   if (!in_function_) {
363     return;
364   }
365   Literal* literal = stmt->expression()->AsLiteral();
366   if (literal) {
367     VisitLiteral(literal, true);
368   } else {
369     RECURSE(
370         VisitWithExpectation(stmt->expression(), Type::Any(),
371                              "return expression expected to have return type"));
372   }
373   if (!computed_type_->Is(return_type_) || !return_type_->Is(computed_type_)) {
374     FAIL(stmt->expression(), "return type does not match function signature");
375   }
376 }
377 
378 
VisitWithStatement(WithStatement * stmt)379 void AsmTyper::VisitWithStatement(WithStatement* stmt) {
380   FAIL(stmt, "bad with statement");
381 }
382 
383 
VisitSwitchStatement(SwitchStatement * stmt)384 void AsmTyper::VisitSwitchStatement(SwitchStatement* stmt) {
385   if (!in_function_) {
386     FAIL(stmt, "switch statement inside module body");
387   }
388   RECURSE(VisitWithExpectation(stmt->tag(), cache_.kAsmSigned,
389                                "switch expression non-integer"));
390   ZoneList<CaseClause*>* clauses = stmt->cases();
391   ZoneSet<int32_t> cases(zone());
392   for (int i = 0; i < clauses->length(); ++i) {
393     CaseClause* clause = clauses->at(i);
394     if (clause->is_default()) {
395       if (i != clauses->length() - 1) {
396         FAIL(clause, "default case out of order");
397       }
398     } else {
399       Expression* label = clause->label();
400       RECURSE(VisitWithExpectation(label, cache_.kAsmSigned,
401                                    "case label non-integer"));
402       if (!label->IsLiteral()) FAIL(label, "non-literal case label");
403       Handle<Object> value = label->AsLiteral()->value();
404       int32_t value32;
405       if (!value->ToInt32(&value32)) FAIL(label, "illegal case label value");
406       if (cases.find(value32) != cases.end()) {
407         FAIL(label, "duplicate case value");
408       }
409       cases.insert(value32);
410     }
411     // TODO(bradnelson): Detect duplicates.
412     ZoneList<Statement*>* stmts = clause->statements();
413     RECURSE(VisitStatements(stmts));
414   }
415   if (cases.size() > 0) {
416     int64_t min_case = *cases.begin();
417     int64_t max_case = *cases.rbegin();
418     if (max_case - min_case > std::numeric_limits<int32_t>::max()) {
419       FAIL(stmt, "case range too large");
420     }
421   }
422 }
423 
424 
VisitCaseClause(CaseClause * clause)425 void AsmTyper::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
426 
427 
VisitDoWhileStatement(DoWhileStatement * stmt)428 void AsmTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
429   if (!in_function_) {
430     FAIL(stmt, "do statement inside module body");
431   }
432   RECURSE(Visit(stmt->body()));
433   RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
434                                "do condition expected to be integer"));
435 }
436 
437 
VisitWhileStatement(WhileStatement * stmt)438 void AsmTyper::VisitWhileStatement(WhileStatement* stmt) {
439   if (!in_function_) {
440     FAIL(stmt, "while statement inside module body");
441   }
442   RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
443                                "while condition expected to be integer"));
444   RECURSE(Visit(stmt->body()));
445 }
446 
447 
VisitForStatement(ForStatement * stmt)448 void AsmTyper::VisitForStatement(ForStatement* stmt) {
449   if (!in_function_) {
450     FAIL(stmt, "for statement inside module body");
451   }
452   if (stmt->init() != NULL) {
453     RECURSE(Visit(stmt->init()));
454   }
455   if (stmt->cond() != NULL) {
456     RECURSE(VisitWithExpectation(stmt->cond(), cache_.kAsmSigned,
457                                  "for condition expected to be integer"));
458   }
459   if (stmt->next() != NULL) {
460     RECURSE(Visit(stmt->next()));
461   }
462   RECURSE(Visit(stmt->body()));
463 }
464 
465 
VisitForInStatement(ForInStatement * stmt)466 void AsmTyper::VisitForInStatement(ForInStatement* stmt) {
467   FAIL(stmt, "for-in statement encountered");
468 }
469 
470 
VisitForOfStatement(ForOfStatement * stmt)471 void AsmTyper::VisitForOfStatement(ForOfStatement* stmt) {
472   FAIL(stmt, "for-of statement encountered");
473 }
474 
475 
VisitTryCatchStatement(TryCatchStatement * stmt)476 void AsmTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
477   FAIL(stmt, "try statement encountered");
478 }
479 
480 
VisitTryFinallyStatement(TryFinallyStatement * stmt)481 void AsmTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
482   FAIL(stmt, "try statement encountered");
483 }
484 
485 
VisitDebuggerStatement(DebuggerStatement * stmt)486 void AsmTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
487   FAIL(stmt, "debugger statement encountered");
488 }
489 
490 
VisitFunctionLiteral(FunctionLiteral * expr)491 void AsmTyper::VisitFunctionLiteral(FunctionLiteral* expr) {
492   Scope* scope = expr->scope();
493   DCHECK(scope->is_function_scope());
494   if (in_function_) {
495     FAIL(expr, "invalid nested function");
496   }
497 
498   if (!expr->bounds().upper->IsFunction()) {
499     FAIL(expr, "invalid function literal");
500   }
501 
502   Type::FunctionType* type = expr->bounds().upper->AsFunction();
503   Type* save_return_type = return_type_;
504   return_type_ = type->Result();
505   in_function_ = true;
506   local_variable_type_.Clear();
507   RECURSE(VisitDeclarations(scope->declarations()));
508   RECURSE(VisitStatements(expr->body()));
509   in_function_ = false;
510   return_type_ = save_return_type;
511   IntersectResult(expr, type);
512 }
513 
514 
VisitNativeFunctionLiteral(NativeFunctionLiteral * expr)515 void AsmTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
516   FAIL(expr, "function info literal encountered");
517 }
518 
519 
VisitDoExpression(DoExpression * expr)520 void AsmTyper::VisitDoExpression(DoExpression* expr) {
521   FAIL(expr, "do-expression encountered");
522 }
523 
524 
VisitConditional(Conditional * expr)525 void AsmTyper::VisitConditional(Conditional* expr) {
526   RECURSE(VisitWithExpectation(expr->condition(), Type::Number(),
527                                "condition expected to be integer"));
528   if (!computed_type_->Is(cache_.kAsmInt)) {
529     FAIL(expr->condition(), "condition must be of type int");
530   }
531 
532   RECURSE(VisitWithExpectation(
533       expr->then_expression(), expected_type_,
534       "conditional then branch type mismatch with enclosing expression"));
535   Type* then_type = StorageType(computed_type_);
536   if (intish_ != 0 || !then_type->Is(cache_.kAsmComparable)) {
537     FAIL(expr->then_expression(), "invalid type in ? then expression");
538   }
539 
540   RECURSE(VisitWithExpectation(
541       expr->else_expression(), expected_type_,
542       "conditional else branch type mismatch with enclosing expression"));
543   Type* else_type = StorageType(computed_type_);
544   if (intish_ != 0 || !else_type->Is(cache_.kAsmComparable)) {
545     FAIL(expr->else_expression(), "invalid type in ? else expression");
546   }
547 
548   if (!then_type->Is(else_type) || !else_type->Is(then_type)) {
549     FAIL(expr, "then and else expressions in ? must have the same type");
550   }
551 
552   IntersectResult(expr, then_type);
553 }
554 
555 
VisitVariableProxy(VariableProxy * expr)556 void AsmTyper::VisitVariableProxy(VariableProxy* expr) {
557   Variable* var = expr->var();
558   VariableInfo* info = GetVariableInfo(var, false);
559   if (info == NULL || info->type == NULL) {
560     if (var->mode() == TEMPORARY) {
561       SetType(var, Type::Any(zone()));
562       info = GetVariableInfo(var, false);
563     } else {
564       FAIL(expr, "unbound variable");
565     }
566   }
567   if (property_info_ != NULL) {
568     SetVariableInfo(var, property_info_);
569     property_info_ = NULL;
570   }
571   Type* type = Type::Intersect(info->type, expected_type_, zone());
572   if (type->Is(cache_.kAsmInt)) {
573     type = cache_.kAsmInt;
574   }
575   info->type = type;
576   intish_ = 0;
577   IntersectResult(expr, type);
578 }
579 
580 
VisitLiteral(Literal * expr,bool is_return)581 void AsmTyper::VisitLiteral(Literal* expr, bool is_return) {
582   intish_ = 0;
583   Handle<Object> value = expr->value();
584   if (value->IsNumber()) {
585     int32_t i;
586     uint32_t u;
587     if (expr->raw_value()->ContainsDot()) {
588       IntersectResult(expr, cache_.kAsmDouble);
589     } else if (!is_return && value->ToUint32(&u)) {
590       if (u <= 0x7fffffff) {
591         IntersectResult(expr, cache_.kAsmFixnum);
592       } else {
593         IntersectResult(expr, cache_.kAsmUnsigned);
594       }
595     } else if (value->ToInt32(&i)) {
596       IntersectResult(expr, cache_.kAsmSigned);
597     } else {
598       FAIL(expr, "illegal number");
599     }
600   } else if (!is_return && value->IsString()) {
601     IntersectResult(expr, Type::String());
602   } else if (value->IsUndefined()) {
603     IntersectResult(expr, Type::Undefined());
604   } else {
605     FAIL(expr, "illegal literal");
606   }
607 }
608 
609 
VisitLiteral(Literal * expr)610 void AsmTyper::VisitLiteral(Literal* expr) { VisitLiteral(expr, false); }
611 
612 
VisitRegExpLiteral(RegExpLiteral * expr)613 void AsmTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
614   FAIL(expr, "regular expression encountered");
615 }
616 
617 
VisitObjectLiteral(ObjectLiteral * expr)618 void AsmTyper::VisitObjectLiteral(ObjectLiteral* expr) {
619   if (in_function_) {
620     FAIL(expr, "object literal in function");
621   }
622   // Allowed for asm module's export declaration.
623   ZoneList<ObjectLiteralProperty*>* props = expr->properties();
624   for (int i = 0; i < props->length(); ++i) {
625     ObjectLiteralProperty* prop = props->at(i);
626     RECURSE(VisitWithExpectation(prop->value(), Type::Any(zone()),
627                                  "object property expected to be a function"));
628     if (!computed_type_->IsFunction()) {
629       FAIL(prop->value(), "non-function in function table");
630     }
631   }
632   IntersectResult(expr, Type::Object(zone()));
633 }
634 
635 
VisitArrayLiteral(ArrayLiteral * expr)636 void AsmTyper::VisitArrayLiteral(ArrayLiteral* expr) {
637   if (in_function_) {
638     FAIL(expr, "array literal inside a function");
639   }
640   // Allowed for function tables.
641   ZoneList<Expression*>* values = expr->values();
642   Type* elem_type = Type::None(zone());
643   for (int i = 0; i < values->length(); ++i) {
644     Expression* value = values->at(i);
645     RECURSE(VisitWithExpectation(value, Type::Any(), "UNREACHABLE"));
646     if (!computed_type_->IsFunction()) {
647       FAIL(value, "array component expected to be a function");
648     }
649     elem_type = Type::Union(elem_type, computed_type_, zone());
650   }
651   array_size_ = values->length();
652   IntersectResult(expr, Type::Array(elem_type, zone()));
653 }
654 
655 
VisitAssignment(Assignment * expr)656 void AsmTyper::VisitAssignment(Assignment* expr) {
657   // Handle function tables and everything else in different passes.
658   if (!in_function_) {
659     if (expr->value()->IsArrayLiteral()) {
660       if (!building_function_tables_) {
661         return;
662       }
663     } else {
664       if (building_function_tables_) {
665         return;
666       }
667     }
668   }
669   if (expr->is_compound()) FAIL(expr, "compound assignment encountered");
670   Type* type = expected_type_;
671   RECURSE(VisitWithExpectation(
672       expr->value(), type, "assignment value expected to match surrounding"));
673   Type* target_type = StorageType(computed_type_);
674   if (intish_ != 0) {
675     FAIL(expr, "intish or floatish assignment");
676   }
677   if (expr->target()->IsVariableProxy()) {
678     RECURSE(VisitWithExpectation(expr->target(), target_type,
679                                  "assignment target expected to match value"));
680   } else if (expr->target()->IsProperty()) {
681     Property* property = expr->target()->AsProperty();
682     RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
683                                  "bad propety object"));
684     if (!computed_type_->IsArray()) {
685       FAIL(property->obj(), "array expected");
686     }
687     VisitHeapAccess(property, true, target_type);
688   }
689   IntersectResult(expr, target_type);
690 }
691 
692 
VisitYield(Yield * expr)693 void AsmTyper::VisitYield(Yield* expr) {
694   FAIL(expr, "yield expression encountered");
695 }
696 
697 
VisitThrow(Throw * expr)698 void AsmTyper::VisitThrow(Throw* expr) {
699   FAIL(expr, "throw statement encountered");
700 }
701 
702 
ElementShiftSize(Type * type)703 int AsmTyper::ElementShiftSize(Type* type) {
704   if (type->Is(cache_.kAsmSize8)) return 0;
705   if (type->Is(cache_.kAsmSize16)) return 1;
706   if (type->Is(cache_.kAsmSize32)) return 2;
707   if (type->Is(cache_.kAsmSize64)) return 3;
708   return -1;
709 }
710 
711 
StorageType(Type * type)712 Type* AsmTyper::StorageType(Type* type) {
713   if (type->Is(cache_.kAsmInt)) {
714     return cache_.kAsmInt;
715   } else {
716     return type;
717   }
718 }
719 
720 
VisitHeapAccess(Property * expr,bool assigning,Type * assignment_type)721 void AsmTyper::VisitHeapAccess(Property* expr, bool assigning,
722                                Type* assignment_type) {
723   Type::ArrayType* array_type = computed_type_->AsArray();
724   size_t size = array_size_;
725   Type* type = array_type->AsArray()->Element();
726   if (type->IsFunction()) {
727     if (assigning) {
728       FAIL(expr, "assigning to function table is illegal");
729     }
730     BinaryOperation* bin = expr->key()->AsBinaryOperation();
731     if (bin == NULL || bin->op() != Token::BIT_AND) {
732       FAIL(expr->key(), "expected & in call");
733     }
734     RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
735                                  "array index expected to be integer"));
736     Literal* right = bin->right()->AsLiteral();
737     if (right == NULL || right->raw_value()->ContainsDot()) {
738       FAIL(right, "call mask must be integer");
739     }
740     RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
741                                  "call mask expected to be integer"));
742     if (static_cast<size_t>(right->raw_value()->AsNumber()) != size - 1) {
743       FAIL(right, "call mask must match function table");
744     }
745     bin->set_bounds(Bounds(cache_.kAsmSigned));
746     IntersectResult(expr, type);
747   } else {
748     Literal* literal = expr->key()->AsLiteral();
749     if (literal) {
750       RECURSE(VisitWithExpectation(literal, cache_.kAsmSigned,
751                                    "array index expected to be integer"));
752     } else {
753       BinaryOperation* bin = expr->key()->AsBinaryOperation();
754       if (bin == NULL || bin->op() != Token::SAR) {
755         FAIL(expr->key(), "expected >> in heap access");
756       }
757       RECURSE(VisitWithExpectation(bin->left(), cache_.kAsmSigned,
758                                    "array index expected to be integer"));
759       Literal* right = bin->right()->AsLiteral();
760       if (right == NULL || right->raw_value()->ContainsDot()) {
761         FAIL(right, "heap access shift must be integer");
762       }
763       RECURSE(VisitWithExpectation(bin->right(), cache_.kAsmSigned,
764                                    "array shift expected to be integer"));
765       int n = static_cast<int>(right->raw_value()->AsNumber());
766       int expected_shift = ElementShiftSize(type);
767       if (expected_shift < 0 || n != expected_shift) {
768         FAIL(right, "heap access shift must match element size");
769       }
770       bin->set_bounds(Bounds(cache_.kAsmSigned));
771     }
772     Type* result_type;
773     if (type->Is(cache_.kAsmIntArrayElement)) {
774       result_type = cache_.kAsmIntQ;
775       intish_ = kMaxUncombinedAdditiveSteps;
776     } else if (type->Is(cache_.kAsmFloat)) {
777       if (assigning) {
778         result_type = cache_.kAsmFloatDoubleQ;
779       } else {
780         result_type = cache_.kAsmFloatQ;
781       }
782       intish_ = 0;
783     } else if (type->Is(cache_.kAsmDouble)) {
784       if (assigning) {
785         result_type = cache_.kAsmFloatDoubleQ;
786         if (intish_ != 0) {
787           FAIL(expr, "Assignment of floatish to Float64Array");
788         }
789       } else {
790         result_type = cache_.kAsmDoubleQ;
791       }
792       intish_ = 0;
793     } else {
794       UNREACHABLE();
795     }
796     if (assigning) {
797       if (!assignment_type->Is(result_type)) {
798         FAIL(expr, "illegal type in assignment");
799       }
800     } else {
801       IntersectResult(expr, expected_type_);
802       IntersectResult(expr, result_type);
803     }
804   }
805 }
806 
807 
IsStdlibObject(Expression * expr)808 bool AsmTyper::IsStdlibObject(Expression* expr) {
809   VariableProxy* proxy = expr->AsVariableProxy();
810   if (proxy == NULL) {
811     return false;
812   }
813   Variable* var = proxy->var();
814   VariableInfo* info = GetVariableInfo(var, false);
815   if (info) {
816     if (info->standard_member == kStdlib) return true;
817   }
818   if (var->location() != VariableLocation::PARAMETER || var->index() != 0) {
819     return false;
820   }
821   info = GetVariableInfo(var, true);
822   info->type = Type::Object();
823   info->standard_member = kStdlib;
824   return true;
825 }
826 
827 
GetReceiverOfPropertyAccess(Expression * expr,const char * name)828 Expression* AsmTyper::GetReceiverOfPropertyAccess(Expression* expr,
829                                                   const char* name) {
830   Property* property = expr->AsProperty();
831   if (property == NULL) {
832     return NULL;
833   }
834   Literal* key = property->key()->AsLiteral();
835   if (key == NULL || !key->IsPropertyName() ||
836       !key->AsPropertyName()->IsUtf8EqualTo(CStrVector(name))) {
837     return NULL;
838   }
839   return property->obj();
840 }
841 
842 
IsMathObject(Expression * expr)843 bool AsmTyper::IsMathObject(Expression* expr) {
844   Expression* obj = GetReceiverOfPropertyAccess(expr, "Math");
845   return obj && IsStdlibObject(obj);
846 }
847 
848 
IsSIMDObject(Expression * expr)849 bool AsmTyper::IsSIMDObject(Expression* expr) {
850   Expression* obj = GetReceiverOfPropertyAccess(expr, "SIMD");
851   return obj && IsStdlibObject(obj);
852 }
853 
854 
IsSIMDTypeObject(Expression * expr,const char * name)855 bool AsmTyper::IsSIMDTypeObject(Expression* expr, const char* name) {
856   Expression* obj = GetReceiverOfPropertyAccess(expr, name);
857   return obj && IsSIMDObject(obj);
858 }
859 
860 
VisitProperty(Property * expr)861 void AsmTyper::VisitProperty(Property* expr) {
862   if (IsMathObject(expr->obj())) {
863     VisitLibraryAccess(&stdlib_math_types_, expr);
864     return;
865   }
866 #define V(NAME, Name, name, lane_count, lane_type)               \
867   if (IsSIMDTypeObject(expr->obj(), #Name)) {                    \
868     VisitLibraryAccess(&stdlib_simd_##name##_types_, expr);      \
869     return;                                                      \
870   }                                                              \
871   if (IsSIMDTypeObject(expr, #Name)) {                           \
872     VariableInfo* info = stdlib_simd_##name##_constructor_type_; \
873     SetResult(expr, info->type);                                 \
874     property_info_ = info;                                       \
875     return;                                                      \
876   }
877   SIMD128_TYPES(V)
878 #undef V
879   if (IsStdlibObject(expr->obj())) {
880     VisitLibraryAccess(&stdlib_types_, expr);
881     return;
882   }
883 
884   property_info_ = NULL;
885 
886   // Only recurse at this point so that we avoid needing
887   // stdlib.Math to have a real type.
888   RECURSE(VisitWithExpectation(expr->obj(), Type::Any(), "bad propety object"));
889 
890   // For heap view or function table access.
891   if (computed_type_->IsArray()) {
892     VisitHeapAccess(expr, false, NULL);
893     return;
894   }
895 
896   // stdlib.x or foreign.x
897   VariableProxy* proxy = expr->obj()->AsVariableProxy();
898   if (proxy != NULL) {
899     Variable* var = proxy->var();
900     if (var->location() == VariableLocation::PARAMETER && var->index() == 1) {
901       // foreign.x is ok.
902       SetResult(expr, expected_type_);
903       return;
904     }
905   }
906 
907   FAIL(expr, "invalid property access");
908 }
909 
910 
VisitCall(Call * expr)911 void AsmTyper::VisitCall(Call* expr) {
912   RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
913                                "callee expected to be any"));
914   StandardMember standard_member = kNone;
915   VariableProxy* proxy = expr->expression()->AsVariableProxy();
916   if (proxy) {
917     standard_member = VariableAsStandardMember(proxy->var());
918   }
919   if (!in_function_ && (proxy == NULL || standard_member != kMathFround)) {
920     FAIL(expr, "calls forbidden outside function bodies");
921   }
922   if (proxy == NULL && !expr->expression()->IsProperty()) {
923     FAIL(expr, "calls must be to bound variables or function tables");
924   }
925   if (computed_type_->IsFunction()) {
926     Type::FunctionType* fun_type = computed_type_->AsFunction();
927     Type* result_type = fun_type->Result();
928     ZoneList<Expression*>* args = expr->arguments();
929     if (fun_type->Arity() != args->length()) {
930       FAIL(expr, "call with wrong arity");
931     }
932     for (int i = 0; i < args->length(); ++i) {
933       Expression* arg = args->at(i);
934       RECURSE(VisitWithExpectation(
935           arg, fun_type->Parameter(i),
936           "call argument expected to match callee parameter"));
937       if (standard_member != kNone && standard_member != kMathFround &&
938           i == 0) {
939         result_type = computed_type_;
940       }
941     }
942     // Handle polymorphic stdlib functions specially.
943     if (standard_member == kMathCeil || standard_member == kMathFloor ||
944         standard_member == kMathSqrt) {
945       if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) &&
946           !args->at(0)->bounds().upper->Is(cache_.kAsmDouble)) {
947         FAIL(expr, "illegal function argument type");
948       }
949     } else if (standard_member == kMathAbs || standard_member == kMathMin ||
950                standard_member == kMathMax) {
951       if (!args->at(0)->bounds().upper->Is(cache_.kAsmFloat) &&
952           !args->at(0)->bounds().upper->Is(cache_.kAsmDouble) &&
953           !args->at(0)->bounds().upper->Is(cache_.kAsmSigned)) {
954         FAIL(expr, "illegal function argument type");
955       }
956       if (args->length() > 1) {
957         Type* other = Type::Intersect(args->at(0)->bounds().upper,
958                                       args->at(1)->bounds().upper, zone());
959         if (!other->Is(cache_.kAsmFloat) && !other->Is(cache_.kAsmDouble) &&
960             !other->Is(cache_.kAsmSigned)) {
961           FAIL(expr, "function arguments types don't match");
962         }
963       }
964     }
965     intish_ = 0;
966     IntersectResult(expr, result_type);
967   } else if (computed_type_->Is(Type::Any())) {
968     // For foreign calls.
969     ZoneList<Expression*>* args = expr->arguments();
970     for (int i = 0; i < args->length(); ++i) {
971       Expression* arg = args->at(i);
972       RECURSE(VisitWithExpectation(arg, Type::Any(),
973                                    "foreign call argument expected to be any"));
974     }
975     intish_ = kMaxUncombinedAdditiveSteps;
976     IntersectResult(expr, Type::Number());
977   } else {
978     FAIL(expr, "invalid callee");
979   }
980 }
981 
982 
VisitCallNew(CallNew * expr)983 void AsmTyper::VisitCallNew(CallNew* expr) {
984   if (in_function_) {
985     FAIL(expr, "new not allowed in module function");
986   }
987   RECURSE(VisitWithExpectation(expr->expression(), Type::Any(),
988                                "expected stdlib function"));
989   if (computed_type_->IsFunction()) {
990     Type::FunctionType* fun_type = computed_type_->AsFunction();
991     ZoneList<Expression*>* args = expr->arguments();
992     if (fun_type->Arity() != args->length())
993       FAIL(expr, "call with wrong arity");
994     for (int i = 0; i < args->length(); ++i) {
995       Expression* arg = args->at(i);
996       RECURSE(VisitWithExpectation(
997           arg, fun_type->Parameter(i),
998           "constructor argument expected to match callee parameter"));
999     }
1000     IntersectResult(expr, fun_type->Result());
1001     return;
1002   }
1003 
1004   FAIL(expr, "ill-typed new operator");
1005 }
1006 
1007 
VisitCallRuntime(CallRuntime * expr)1008 void AsmTyper::VisitCallRuntime(CallRuntime* expr) {
1009   // Allow runtime calls for now.
1010 }
1011 
1012 
VisitUnaryOperation(UnaryOperation * expr)1013 void AsmTyper::VisitUnaryOperation(UnaryOperation* expr) {
1014   switch (expr->op()) {
1015     case Token::NOT:  // Used to encode != and !==
1016       RECURSE(VisitWithExpectation(expr->expression(), cache_.kAsmInt,
1017                                    "operand expected to be integer"));
1018       IntersectResult(expr, cache_.kAsmSigned);
1019       return;
1020     case Token::DELETE:
1021       FAIL(expr, "delete operator encountered");
1022     case Token::VOID:
1023       FAIL(expr, "void operator encountered");
1024     case Token::TYPEOF:
1025       FAIL(expr, "typeof operator encountered");
1026     default:
1027       UNREACHABLE();
1028   }
1029 }
1030 
1031 
VisitCountOperation(CountOperation * expr)1032 void AsmTyper::VisitCountOperation(CountOperation* expr) {
1033   FAIL(expr, "increment or decrement operator encountered");
1034 }
1035 
1036 
VisitIntegerBitwiseOperator(BinaryOperation * expr,Type * left_expected,Type * right_expected,Type * result_type,bool conversion)1037 void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
1038                                            Type* left_expected,
1039                                            Type* right_expected,
1040                                            Type* result_type, bool conversion) {
1041   RECURSE(VisitWithExpectation(expr->left(), Type::Number(),
1042                                "left bitwise operand expected to be a number"));
1043   int left_intish = intish_;
1044   Type* left_type = computed_type_;
1045   if (!left_type->Is(left_expected)) {
1046     FAIL(expr->left(), "left bitwise operand expected to be an integer");
1047   }
1048   if (left_intish > kMaxUncombinedAdditiveSteps) {
1049     FAIL(expr->left(), "too many consecutive additive ops");
1050   }
1051 
1052   RECURSE(
1053       VisitWithExpectation(expr->right(), Type::Number(),
1054                            "right bitwise operand expected to be a number"));
1055   int right_intish = intish_;
1056   Type* right_type = computed_type_;
1057   if (!right_type->Is(right_expected)) {
1058     FAIL(expr->right(), "right bitwise operand expected to be an integer");
1059   }
1060   if (right_intish > kMaxUncombinedAdditiveSteps) {
1061     FAIL(expr->right(), "too many consecutive additive ops");
1062   }
1063 
1064   intish_ = 0;
1065 
1066   if (left_type->Is(cache_.kAsmFixnum) && right_type->Is(cache_.kAsmInt)) {
1067     left_type = right_type;
1068   }
1069   if (right_type->Is(cache_.kAsmFixnum) && left_type->Is(cache_.kAsmInt)) {
1070     right_type = left_type;
1071   }
1072   if (!conversion) {
1073     if (!left_type->Is(right_type) || !right_type->Is(left_type)) {
1074       FAIL(expr, "ill-typed bitwise operation");
1075     }
1076   }
1077   IntersectResult(expr, result_type);
1078 }
1079 
1080 
VisitBinaryOperation(BinaryOperation * expr)1081 void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
1082   switch (expr->op()) {
1083     case Token::COMMA: {
1084       RECURSE(VisitWithExpectation(expr->left(), Type::Any(),
1085                                    "left comma operand expected to be any"));
1086       RECURSE(VisitWithExpectation(expr->right(), Type::Any(),
1087                                    "right comma operand expected to be any"));
1088       IntersectResult(expr, computed_type_);
1089       return;
1090     }
1091     case Token::OR:
1092     case Token::AND:
1093       FAIL(expr, "illegal logical operator");
1094     case Token::BIT_OR: {
1095       // BIT_OR allows Any since it is used as a type coercion.
1096       VisitIntegerBitwiseOperator(expr, Type::Any(), cache_.kAsmInt,
1097                                   cache_.kAsmSigned, true);
1098       return;
1099     }
1100     case Token::BIT_XOR: {
1101       // Handle booleans specially to handle de-sugared !
1102       Literal* left = expr->left()->AsLiteral();
1103       if (left && left->value()->IsBoolean()) {
1104         if (left->ToBooleanIsTrue()) {
1105           left->set_bounds(Bounds(cache_.kSingletonOne));
1106           RECURSE(VisitWithExpectation(expr->right(), cache_.kAsmInt,
1107                                        "not operator expects an integer"));
1108           IntersectResult(expr, cache_.kAsmSigned);
1109           return;
1110         } else {
1111           FAIL(left, "unexpected false");
1112         }
1113       }
1114       // BIT_XOR allows Number since it is used as a type coercion (via ~~).
1115       VisitIntegerBitwiseOperator(expr, Type::Number(), cache_.kAsmInt,
1116                                   cache_.kAsmSigned, true);
1117       return;
1118     }
1119     case Token::SHR: {
1120       VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt,
1121                                   cache_.kAsmUnsigned, false);
1122       return;
1123     }
1124     case Token::SHL:
1125     case Token::SAR:
1126     case Token::BIT_AND: {
1127       VisitIntegerBitwiseOperator(expr, cache_.kAsmInt, cache_.kAsmInt,
1128                                   cache_.kAsmSigned, false);
1129       return;
1130     }
1131     case Token::ADD:
1132     case Token::SUB:
1133     case Token::MUL:
1134     case Token::DIV:
1135     case Token::MOD: {
1136       RECURSE(VisitWithExpectation(
1137           expr->left(), Type::Number(),
1138           "left arithmetic operand expected to be number"));
1139       Type* left_type = computed_type_;
1140       int left_intish = intish_;
1141       RECURSE(VisitWithExpectation(
1142           expr->right(), Type::Number(),
1143           "right arithmetic operand expected to be number"));
1144       Type* right_type = computed_type_;
1145       int right_intish = intish_;
1146       Type* type = Type::Union(left_type, right_type, zone());
1147       if (type->Is(cache_.kAsmInt)) {
1148         if (expr->op() == Token::MUL) {
1149           Literal* right = expr->right()->AsLiteral();
1150           if (!right) {
1151             FAIL(expr, "direct integer multiply forbidden");
1152           }
1153           if (!right->value()->IsNumber()) {
1154             FAIL(expr, "multiply must be by an integer");
1155           }
1156           int32_t i;
1157           if (!right->value()->ToInt32(&i)) {
1158             FAIL(expr, "multiply must be a signed integer");
1159           }
1160           i = abs(i);
1161           if (i >= 1 << 20) {
1162             FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
1163           }
1164           intish_ = i;
1165           IntersectResult(expr, cache_.kAsmInt);
1166           return;
1167         } else {
1168           intish_ = left_intish + right_intish + 1;
1169           if (expr->op() == Token::ADD || expr->op() == Token::SUB) {
1170             if (intish_ > kMaxUncombinedAdditiveSteps) {
1171               FAIL(expr, "too many consecutive additive ops");
1172             }
1173           } else {
1174             if (intish_ > kMaxUncombinedMultiplicativeSteps) {
1175               FAIL(expr, "too many consecutive multiplicative ops");
1176             }
1177           }
1178           IntersectResult(expr, cache_.kAsmInt);
1179           return;
1180         }
1181       } else if (expr->op() == Token::MUL && expr->right()->IsLiteral() &&
1182                  right_type->Is(cache_.kAsmDouble)) {
1183         // For unary +, expressed as x * 1.0
1184         IntersectResult(expr, cache_.kAsmDouble);
1185         return;
1186       } else if (type->Is(cache_.kAsmFloat) && expr->op() != Token::MOD) {
1187         if (left_intish != 0 || right_intish != 0) {
1188           FAIL(expr, "float operation before required fround");
1189         }
1190         IntersectResult(expr, cache_.kAsmFloat);
1191         intish_ = 1;
1192         return;
1193       } else if (type->Is(cache_.kAsmDouble)) {
1194         IntersectResult(expr, cache_.kAsmDouble);
1195         return;
1196       } else {
1197         FAIL(expr, "ill-typed arithmetic operation");
1198       }
1199     }
1200     default:
1201       UNREACHABLE();
1202   }
1203 }
1204 
1205 
VisitCompareOperation(CompareOperation * expr)1206 void AsmTyper::VisitCompareOperation(CompareOperation* expr) {
1207   Token::Value op = expr->op();
1208   if (op != Token::EQ && op != Token::NE && op != Token::LT &&
1209       op != Token::LTE && op != Token::GT && op != Token::GTE) {
1210     FAIL(expr, "illegal comparison operator");
1211   }
1212 
1213   RECURSE(
1214       VisitWithExpectation(expr->left(), Type::Number(),
1215                            "left comparison operand expected to be number"));
1216   Type* left_type = computed_type_;
1217   if (!left_type->Is(cache_.kAsmComparable)) {
1218     FAIL(expr->left(), "bad type on left side of comparison");
1219   }
1220 
1221   RECURSE(
1222       VisitWithExpectation(expr->right(), Type::Number(),
1223                            "right comparison operand expected to be number"));
1224   Type* right_type = computed_type_;
1225   if (!right_type->Is(cache_.kAsmComparable)) {
1226     FAIL(expr->right(), "bad type on right side of comparison");
1227   }
1228 
1229   if (!left_type->Is(right_type) && !right_type->Is(left_type)) {
1230     FAIL(expr, "left and right side of comparison must match");
1231   }
1232 
1233   IntersectResult(expr, cache_.kAsmSigned);
1234 }
1235 
1236 
VisitThisFunction(ThisFunction * expr)1237 void AsmTyper::VisitThisFunction(ThisFunction* expr) {
1238   FAIL(expr, "this function not allowed");
1239 }
1240 
1241 
VisitDeclarations(ZoneList<Declaration * > * decls)1242 void AsmTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
1243   for (int i = 0; i < decls->length(); ++i) {
1244     Declaration* decl = decls->at(i);
1245     RECURSE(Visit(decl));
1246   }
1247 }
1248 
1249 
VisitImportDeclaration(ImportDeclaration * decl)1250 void AsmTyper::VisitImportDeclaration(ImportDeclaration* decl) {
1251   FAIL(decl, "import declaration encountered");
1252 }
1253 
1254 
VisitExportDeclaration(ExportDeclaration * decl)1255 void AsmTyper::VisitExportDeclaration(ExportDeclaration* decl) {
1256   FAIL(decl, "export declaration encountered");
1257 }
1258 
1259 
VisitClassLiteral(ClassLiteral * expr)1260 void AsmTyper::VisitClassLiteral(ClassLiteral* expr) {
1261   FAIL(expr, "class literal not allowed");
1262 }
1263 
1264 
VisitSpread(Spread * expr)1265 void AsmTyper::VisitSpread(Spread* expr) { FAIL(expr, "spread not allowed"); }
1266 
1267 
VisitSuperPropertyReference(SuperPropertyReference * expr)1268 void AsmTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {
1269   FAIL(expr, "super property reference not allowed");
1270 }
1271 
1272 
VisitSuperCallReference(SuperCallReference * expr)1273 void AsmTyper::VisitSuperCallReference(SuperCallReference* expr) {
1274   FAIL(expr, "call reference not allowed");
1275 }
1276 
1277 
InitializeStdlibSIMD()1278 void AsmTyper::InitializeStdlibSIMD() {
1279 #define V(NAME, Name, name, lane_count, lane_type)                            \
1280   {                                                                           \
1281     Type* type = Type::Function(Type::Name(isolate_, zone()), Type::Any(),    \
1282                                 lane_count, zone());                          \
1283     for (int i = 0; i < lane_count; ++i) {                                    \
1284       type->AsFunction()->InitParameter(i, Type::Number());                   \
1285     }                                                                         \
1286     stdlib_simd_##name##_constructor_type_ = new (zone()) VariableInfo(type); \
1287     stdlib_simd_##name##_constructor_type_->is_constructor_function = true;   \
1288   }
1289   SIMD128_TYPES(V)
1290 #undef V
1291 }
1292 
1293 
InitializeStdlib()1294 void AsmTyper::InitializeStdlib() {
1295   if (allow_simd_) {
1296     InitializeStdlibSIMD();
1297   }
1298   Type* number_type = Type::Number(zone());
1299   Type* double_type = cache_.kAsmDouble;
1300   Type* double_fn1_type = Type::Function(double_type, double_type, zone());
1301   Type* double_fn2_type =
1302       Type::Function(double_type, double_type, double_type, zone());
1303 
1304   Type* fround_type = Type::Function(cache_.kAsmFloat, number_type, zone());
1305   Type* imul_type =
1306       Type::Function(cache_.kAsmSigned, cache_.kAsmInt, cache_.kAsmInt, zone());
1307   // TODO(bradnelson): currently only approximating the proper intersection type
1308   // (which we cannot currently represent).
1309   Type* number_fn1_type = Type::Function(number_type, number_type, zone());
1310   Type* number_fn2_type =
1311       Type::Function(number_type, number_type, number_type, zone());
1312 
1313   struct Assignment {
1314     const char* name;
1315     StandardMember standard_member;
1316     Type* type;
1317   };
1318 
1319   const Assignment math[] = {{"PI", kMathPI, double_type},
1320                              {"E", kMathE, double_type},
1321                              {"LN2", kMathLN2, double_type},
1322                              {"LN10", kMathLN10, double_type},
1323                              {"LOG2E", kMathLOG2E, double_type},
1324                              {"LOG10E", kMathLOG10E, double_type},
1325                              {"SQRT2", kMathSQRT2, double_type},
1326                              {"SQRT1_2", kMathSQRT1_2, double_type},
1327                              {"imul", kMathImul, imul_type},
1328                              {"abs", kMathAbs, number_fn1_type},
1329                              {"ceil", kMathCeil, number_fn1_type},
1330                              {"floor", kMathFloor, number_fn1_type},
1331                              {"fround", kMathFround, fround_type},
1332                              {"pow", kMathPow, double_fn2_type},
1333                              {"exp", kMathExp, double_fn1_type},
1334                              {"log", kMathLog, double_fn1_type},
1335                              {"min", kMathMin, number_fn2_type},
1336                              {"max", kMathMax, number_fn2_type},
1337                              {"sqrt", kMathSqrt, number_fn1_type},
1338                              {"cos", kMathCos, double_fn1_type},
1339                              {"sin", kMathSin, double_fn1_type},
1340                              {"tan", kMathTan, double_fn1_type},
1341                              {"acos", kMathAcos, double_fn1_type},
1342                              {"asin", kMathAsin, double_fn1_type},
1343                              {"atan", kMathAtan, double_fn1_type},
1344                              {"atan2", kMathAtan2, double_fn2_type}};
1345   for (unsigned i = 0; i < arraysize(math); ++i) {
1346     stdlib_math_types_[math[i].name] = new (zone()) VariableInfo(math[i].type);
1347     stdlib_math_types_[math[i].name]->standard_member = math[i].standard_member;
1348   }
1349   stdlib_math_types_["fround"]->is_check_function = true;
1350 
1351   stdlib_types_["Infinity"] = new (zone()) VariableInfo(double_type);
1352   stdlib_types_["Infinity"]->standard_member = kInfinity;
1353   stdlib_types_["NaN"] = new (zone()) VariableInfo(double_type);
1354   stdlib_types_["NaN"]->standard_member = kNaN;
1355   Type* buffer_type = Type::Any(zone());
1356 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size) \
1357   stdlib_types_[#TypeName "Array"] = new (zone()) VariableInfo(  \
1358       Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
1359   TYPED_ARRAYS(TYPED_ARRAY)
1360 #undef TYPED_ARRAY
1361 
1362 #define TYPED_ARRAY(TypeName, type_name, TYPE_NAME, ctype, size)     \
1363   stdlib_heap_types_[#TypeName "Array"] = new (zone()) VariableInfo( \
1364       Type::Function(cache_.k##TypeName##Array, buffer_type, zone()));
1365   TYPED_ARRAYS(TYPED_ARRAY)
1366 #undef TYPED_ARRAY
1367 }
1368 
1369 
VisitLibraryAccess(ObjectTypeMap * map,Property * expr)1370 void AsmTyper::VisitLibraryAccess(ObjectTypeMap* map, Property* expr) {
1371   Literal* key = expr->key()->AsLiteral();
1372   if (key == NULL || !key->IsPropertyName())
1373     FAIL(expr, "invalid key used on stdlib member");
1374   Handle<String> name = key->AsPropertyName();
1375   VariableInfo* info = LibType(map, name);
1376   if (info == NULL || info->type == NULL) FAIL(expr, "unknown stdlib function");
1377   SetResult(expr, info->type);
1378   property_info_ = info;
1379 }
1380 
1381 
LibType(ObjectTypeMap * map,Handle<String> name)1382 AsmTyper::VariableInfo* AsmTyper::LibType(ObjectTypeMap* map,
1383                                           Handle<String> name) {
1384   base::SmartArrayPointer<char> aname = name->ToCString();
1385   ObjectTypeMap::iterator i = map->find(std::string(aname.get()));
1386   if (i == map->end()) {
1387     return NULL;
1388   }
1389   return i->second;
1390 }
1391 
1392 
SetType(Variable * variable,Type * type)1393 void AsmTyper::SetType(Variable* variable, Type* type) {
1394   VariableInfo* info = GetVariableInfo(variable, true);
1395   info->type = type;
1396 }
1397 
1398 
GetType(Variable * variable)1399 Type* AsmTyper::GetType(Variable* variable) {
1400   VariableInfo* info = GetVariableInfo(variable, false);
1401   if (!info) return NULL;
1402   return info->type;
1403 }
1404 
1405 
GetVariableInfo(Variable * variable,bool setting)1406 AsmTyper::VariableInfo* AsmTyper::GetVariableInfo(Variable* variable,
1407                                                   bool setting) {
1408   ZoneHashMap::Entry* entry;
1409   ZoneHashMap* map;
1410   if (in_function_) {
1411     map = &local_variable_type_;
1412   } else {
1413     map = &global_variable_type_;
1414   }
1415   if (setting) {
1416     entry = map->LookupOrInsert(variable, ComputePointerHash(variable),
1417                                 ZoneAllocationPolicy(zone()));
1418   } else {
1419     entry = map->Lookup(variable, ComputePointerHash(variable));
1420     if (!entry && in_function_) {
1421       entry =
1422           global_variable_type_.Lookup(variable, ComputePointerHash(variable));
1423       if (entry && entry->value) {
1424       }
1425     }
1426   }
1427   if (!entry) return NULL;
1428   if (!entry->value) {
1429     if (!setting) return NULL;
1430     entry->value = new (zone()) VariableInfo;
1431   }
1432   return reinterpret_cast<VariableInfo*>(entry->value);
1433 }
1434 
1435 
SetVariableInfo(Variable * variable,const VariableInfo * info)1436 void AsmTyper::SetVariableInfo(Variable* variable, const VariableInfo* info) {
1437   VariableInfo* dest = GetVariableInfo(variable, true);
1438   dest->type = info->type;
1439   dest->is_check_function = info->is_check_function;
1440   dest->is_constructor_function = info->is_constructor_function;
1441   dest->standard_member = info->standard_member;
1442 }
1443 
1444 
VariableAsStandardMember(Variable * variable)1445 AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(
1446     Variable* variable) {
1447   VariableInfo* info = GetVariableInfo(variable, false);
1448   if (!info) return kNone;
1449   return info->standard_member;
1450 }
1451 
1452 
SetResult(Expression * expr,Type * type)1453 void AsmTyper::SetResult(Expression* expr, Type* type) {
1454   computed_type_ = type;
1455   expr->set_bounds(Bounds(computed_type_));
1456 }
1457 
1458 
IntersectResult(Expression * expr,Type * type)1459 void AsmTyper::IntersectResult(Expression* expr, Type* type) {
1460   computed_type_ = type;
1461   Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
1462   expr->set_bounds(Bounds(bounded_type));
1463 }
1464 
1465 
VisitWithExpectation(Expression * expr,Type * expected_type,const char * msg)1466 void AsmTyper::VisitWithExpectation(Expression* expr, Type* expected_type,
1467                                     const char* msg) {
1468   Type* save = expected_type_;
1469   expected_type_ = expected_type;
1470   RECURSE(Visit(expr));
1471   Type* bounded_type = Type::Intersect(computed_type_, expected_type_, zone());
1472   if (bounded_type->Is(Type::None(zone()))) {
1473 #ifdef DEBUG
1474     PrintF("Computed type: ");
1475     computed_type_->Print();
1476     PrintF("Expected type: ");
1477     expected_type_->Print();
1478 #endif
1479     FAIL(expr, msg);
1480   }
1481   expected_type_ = save;
1482 }
1483 
1484 
VisitRewritableAssignmentExpression(RewritableAssignmentExpression * expr)1485 void AsmTyper::VisitRewritableAssignmentExpression(
1486     RewritableAssignmentExpression* expr) {
1487   RECURSE(Visit(expr->expression()));
1488 }
1489 
1490 
1491 }  // namespace internal
1492 }  // namespace v8
1493