Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 // Required to get M_E etc. in MSVC. | 7 // Required to get M_E etc. in MSVC. |
| 8 #if defined(_WIN32) | 8 #if defined(_WIN32) |
| 9 #define _USE_MATH_DEFINES | 9 #define _USE_MATH_DEFINES |
| 10 #endif | 10 #endif |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 namespace internal { | 23 namespace internal { |
| 24 namespace wasm { | 24 namespace wasm { |
| 25 | 25 |
| 26 #define RECURSE(call) \ | 26 #define RECURSE(call) \ |
| 27 do { \ | 27 do { \ |
| 28 DCHECK(!HasStackOverflow()); \ | 28 DCHECK(!HasStackOverflow()); \ |
| 29 call; \ | 29 call; \ |
| 30 if (HasStackOverflow()) return; \ | 30 if (HasStackOverflow()) return; \ |
| 31 } while (false) | 31 } while (false) |
| 32 | 32 |
| 33 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; | |
| 33 | 34 |
| 34 class AsmWasmBuilderImpl : public AstVisitor { | 35 class AsmWasmBuilderImpl : public AstVisitor { |
| 35 public: | 36 public: |
| 36 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 37 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
| 37 Handle<Object> foreign, AsmTyper* typer) | 38 Handle<Object> foreign, AsmTyper* typer) |
| 38 : local_variables_(HashMap::PointersMatch, | 39 : local_variables_(HashMap::PointersMatch, |
| 39 ZoneHashMap::kDefaultHashMapCapacity, | 40 ZoneHashMap::kDefaultHashMapCapacity, |
| 40 ZoneAllocationPolicy(zone)), | 41 ZoneAllocationPolicy(zone)), |
| 41 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | 42 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, |
| 42 ZoneAllocationPolicy(zone)), | 43 ZoneAllocationPolicy(zone)), |
| 43 global_variables_(HashMap::PointersMatch, | 44 global_variables_(HashMap::PointersMatch, |
| 44 ZoneHashMap::kDefaultHashMapCapacity, | 45 ZoneHashMap::kDefaultHashMapCapacity, |
| 45 ZoneAllocationPolicy(zone)), | 46 ZoneAllocationPolicy(zone)), |
| 46 in_function_(false), | 47 scope_(kModuleScope), |
| 47 is_set_op_(false), | |
| 48 marking_exported(false), | |
| 49 builder_(new (zone) WasmModuleBuilder(zone)), | 48 builder_(new (zone) WasmModuleBuilder(zone)), |
| 50 current_function_builder_(nullptr), | 49 current_function_builder_(nullptr), |
| 51 literal_(literal), | 50 literal_(literal), |
| 52 isolate_(isolate), | 51 isolate_(isolate), |
| 53 zone_(zone), | 52 zone_(zone), |
| 54 foreign_(foreign), | 53 foreign_(foreign), |
| 55 typer_(typer), | 54 typer_(typer), |
| 56 cache_(TypeCache::Get()), | 55 cache_(TypeCache::Get()), |
| 57 breakable_blocks_(zone), | 56 breakable_blocks_(zone), |
| 58 block_size_(0), | |
| 59 init_function_index_(0), | 57 init_function_index_(0), |
| 60 next_table_index_(0), | 58 next_table_index_(0), |
| 61 function_tables_(HashMap::PointersMatch, | 59 function_tables_(HashMap::PointersMatch, |
| 62 ZoneHashMap::kDefaultHashMapCapacity, | 60 ZoneHashMap::kDefaultHashMapCapacity, |
| 63 ZoneAllocationPolicy(zone)), | 61 ZoneAllocationPolicy(zone)), |
| 64 imported_function_table_(this) { | 62 imported_function_table_(this) { |
| 65 InitializeAstVisitor(isolate); | 63 InitializeAstVisitor(isolate); |
| 66 } | 64 } |
| 67 | 65 |
| 68 void InitializeInitFunction() { | 66 void InitializeInitFunction() { |
| 69 init_function_index_ = builder_->AddFunction(); | 67 init_function_index_ = builder_->AddFunction(); |
| 70 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 68 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 71 current_function_builder_->ReturnType(kAstStmt); | 69 current_function_builder_->ReturnType(kAstStmt); |
| 72 builder_->MarkStartFunction(init_function_index_); | 70 builder_->MarkStartFunction(init_function_index_); |
| 73 current_function_builder_ = nullptr; | 71 current_function_builder_ = nullptr; |
| 74 } | 72 } |
| 75 | 73 |
| 76 void Compile() { | 74 void Compile() { |
| 77 InitializeInitFunction(); | 75 InitializeInitFunction(); |
| 78 RECURSE(VisitFunctionLiteral(literal_)); | 76 RECURSE(VisitFunctionLiteral(literal_)); |
| 79 } | 77 } |
| 80 | 78 |
| 81 void VisitVariableDeclaration(VariableDeclaration* decl) {} | 79 void VisitVariableDeclaration(VariableDeclaration* decl) {} |
| 82 | 80 |
| 83 void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 81 void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 84 DCHECK(!in_function_); | 82 DCHECK_EQ(kModuleScope, scope_); |
| 85 DCHECK_NULL(current_function_builder_); | 83 DCHECK_NULL(current_function_builder_); |
| 86 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); | 84 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); |
| 87 current_function_builder_ = builder_->FunctionAt(index); | 85 current_function_builder_ = builder_->FunctionAt(index); |
| 88 in_function_ = true; | 86 scope_ = kFuncScope; |
| 89 RECURSE(Visit(decl->fun())); | 87 RECURSE(Visit(decl->fun())); |
| 90 in_function_ = false; | 88 scope_ = kModuleScope; |
| 91 current_function_builder_ = nullptr; | 89 current_function_builder_ = nullptr; |
| 92 local_variables_.Clear(); | 90 local_variables_.Clear(); |
| 93 } | 91 } |
| 94 | 92 |
| 95 void VisitImportDeclaration(ImportDeclaration* decl) {} | 93 void VisitImportDeclaration(ImportDeclaration* decl) {} |
| 96 | 94 |
| 97 void VisitExportDeclaration(ExportDeclaration* decl) {} | 95 void VisitExportDeclaration(ExportDeclaration* decl) {} |
| 98 | 96 |
| 99 void VisitStatements(ZoneList<Statement*>* stmts) { | 97 void VisitStatements(ZoneList<Statement*>* stmts) { |
| 100 for (int i = 0; i < stmts->length(); ++i) { | 98 for (int i = 0; i < stmts->length(); ++i) { |
| 101 Statement* stmt = stmts->at(i); | 99 Statement* stmt = stmts->at(i); |
| 102 RECURSE(Visit(stmt)); | 100 RECURSE(Visit(stmt)); |
| 103 if (stmt->IsJump()) break; | 101 if (stmt->IsJump()) break; |
| 104 } | 102 } |
| 105 } | 103 } |
| 106 | 104 |
| 107 void VisitBlock(Block* stmt) { | 105 void VisitBlock(Block* stmt) { |
| 108 if (stmt->statements()->length() == 1) { | 106 if (stmt->statements()->length() == 1) { |
| 109 ExpressionStatement* expr = | 107 ExpressionStatement* expr = |
| 110 stmt->statements()->at(0)->AsExpressionStatement(); | 108 stmt->statements()->at(0)->AsExpressionStatement(); |
| 111 if (expr != nullptr) { | 109 if (expr != nullptr) { |
| 112 if (expr->expression()->IsAssignment()) { | 110 if (expr->expression()->IsAssignment()) { |
| 113 RECURSE(VisitExpressionStatement(expr)); | 111 RECURSE(VisitExpressionStatement(expr)); |
| 114 return; | 112 return; |
| 115 } | 113 } |
| 116 } | 114 } |
| 117 } | 115 } |
| 118 if (in_function_) { | 116 if (scope_ == kFuncScope) { |
| 119 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, | 117 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |
| 120 false, | 118 false); |
| 121 static_cast<byte>(stmt->statements()->length())); | |
| 122 RECURSE(VisitStatements(stmt->statements())); | 119 RECURSE(VisitStatements(stmt->statements())); |
| 123 DCHECK(block_size_ >= 0); | |
| 124 } else { | 120 } else { |
| 125 RECURSE(VisitStatements(stmt->statements())); | 121 RECURSE(VisitStatements(stmt->statements())); |
| 126 } | 122 } |
| 127 } | 123 } |
| 128 | 124 |
| 129 class BlockVisitor { | 125 class BlockVisitor { |
| 130 private: | 126 private: |
| 131 int prev_block_size_; | |
| 132 uint32_t index_; | |
| 133 AsmWasmBuilderImpl* builder_; | 127 AsmWasmBuilderImpl* builder_; |
| 134 | 128 |
| 135 public: | 129 public: |
| 136 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, | 130 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, |
| 137 WasmOpcode opcode, bool is_loop, int initial_block_size) | 131 WasmOpcode opcode, bool is_loop) |
| 138 : builder_(builder) { | 132 : builder_(builder) { |
| 139 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); | 133 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); |
| 140 builder_->current_function_builder_->Emit(opcode); | 134 builder_->current_function_builder_->Emit(opcode); |
| 141 index_ = | |
| 142 builder_->current_function_builder_->EmitEditableVarIntImmediate(); | |
| 143 prev_block_size_ = builder_->block_size_; | |
| 144 builder_->block_size_ = initial_block_size; | |
| 145 } | 135 } |
| 146 ~BlockVisitor() { | 136 ~BlockVisitor() { |
| 147 builder_->current_function_builder_->EditVarIntImmediate( | 137 builder_->current_function_builder_->Emit(kExprEnd); |
| 148 index_, builder_->block_size_); | |
| 149 builder_->block_size_ = prev_block_size_; | |
| 150 builder_->breakable_blocks_.pop_back(); | 138 builder_->breakable_blocks_.pop_back(); |
| 151 } | 139 } |
| 152 }; | 140 }; |
| 153 | 141 |
| 154 void VisitExpressionStatement(ExpressionStatement* stmt) { | 142 void VisitExpressionStatement(ExpressionStatement* stmt) { |
| 155 RECURSE(Visit(stmt->expression())); | 143 RECURSE(Visit(stmt->expression())); |
| 156 } | 144 } |
| 157 | 145 |
| 158 void VisitEmptyStatement(EmptyStatement* stmt) {} | 146 void VisitEmptyStatement(EmptyStatement* stmt) {} |
| 159 | 147 |
| 160 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } | 148 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } |
| 161 | 149 |
| 162 void VisitIfStatement(IfStatement* stmt) { | 150 void VisitIfStatement(IfStatement* stmt) { |
| 163 DCHECK(in_function_); | 151 DCHECK_EQ(kFuncScope, scope_); |
| 164 if (stmt->HasElseStatement()) { | |
| 165 current_function_builder_->Emit(kExprIfElse); | |
| 166 } else { | |
| 167 current_function_builder_->Emit(kExprIf); | |
| 168 } | |
| 169 RECURSE(Visit(stmt->condition())); | 152 RECURSE(Visit(stmt->condition())); |
| 153 current_function_builder_->Emit(kExprIf); | |
| 170 if (stmt->HasThenStatement()) { | 154 if (stmt->HasThenStatement()) { |
| 171 RECURSE(Visit(stmt->then_statement())); | 155 RECURSE(Visit(stmt->then_statement())); |
| 172 } else { | |
| 173 current_function_builder_->Emit(kExprNop); | |
| 174 } | 156 } |
| 175 if (stmt->HasElseStatement()) { | 157 if (stmt->HasElseStatement()) { |
| 158 current_function_builder_->Emit(kExprElse); | |
| 176 RECURSE(Visit(stmt->else_statement())); | 159 RECURSE(Visit(stmt->else_statement())); |
| 177 } | 160 } |
| 161 current_function_builder_->Emit(kExprEnd); | |
| 178 } | 162 } |
| 179 | 163 |
| 180 void VisitContinueStatement(ContinueStatement* stmt) { | 164 void VisitContinueStatement(ContinueStatement* stmt) { |
| 181 DCHECK(in_function_); | 165 DCHECK_EQ(kFuncScope, scope_); |
| 182 DCHECK_NOT_NULL(stmt->target()); | 166 DCHECK_NOT_NULL(stmt->target()); |
| 183 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 167 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
| 184 int block_distance = 0; | 168 int block_distance = 0; |
| 185 for (; i >= 0; i--) { | 169 for (; i >= 0; i--) { |
| 186 auto elem = breakable_blocks_.at(i); | 170 auto elem = breakable_blocks_.at(i); |
| 187 if (elem.first == stmt->target()) { | 171 if (elem.first == stmt->target()) { |
| 188 DCHECK(elem.second); | 172 DCHECK(elem.second); |
| 189 break; | 173 break; |
| 190 } else if (elem.second) { | 174 } else if (elem.second) { |
| 191 block_distance += 2; | 175 block_distance += 2; |
| 192 } else { | 176 } else { |
| 193 block_distance += 1; | 177 block_distance += 1; |
| 194 } | 178 } |
| 195 } | 179 } |
| 196 DCHECK(i >= 0); | 180 DCHECK(i >= 0); |
| 181 current_function_builder_->Emit(kExprNop); | |
| 197 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | 182 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); |
| 198 current_function_builder_->Emit(kExprNop); | |
| 199 } | 183 } |
| 200 | 184 |
| 201 void VisitBreakStatement(BreakStatement* stmt) { | 185 void VisitBreakStatement(BreakStatement* stmt) { |
| 202 DCHECK(in_function_); | 186 DCHECK_EQ(kFuncScope, scope_); |
| 203 DCHECK_NOT_NULL(stmt->target()); | 187 DCHECK_NOT_NULL(stmt->target()); |
| 204 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 188 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
| 205 int block_distance = 0; | 189 int block_distance = 0; |
| 206 for (; i >= 0; i--) { | 190 for (; i >= 0; i--) { |
| 207 auto elem = breakable_blocks_.at(i); | 191 auto elem = breakable_blocks_.at(i); |
| 208 if (elem.first == stmt->target()) { | 192 if (elem.first == stmt->target()) { |
| 209 if (elem.second) { | 193 if (elem.second) { |
| 210 block_distance++; | 194 block_distance++; |
| 211 } | 195 } |
| 212 break; | 196 break; |
| 213 } else if (elem.second) { | 197 } else if (elem.second) { |
| 214 block_distance += 2; | 198 block_distance += 2; |
| 215 } else { | 199 } else { |
| 216 block_distance += 1; | 200 block_distance += 1; |
| 217 } | 201 } |
| 218 } | 202 } |
| 219 DCHECK(i >= 0); | 203 DCHECK(i >= 0); |
| 204 current_function_builder_->Emit(kExprNop); | |
| 220 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | 205 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); |
| 221 current_function_builder_->Emit(kExprNop); | |
| 222 } | 206 } |
| 223 | 207 |
| 224 void VisitReturnStatement(ReturnStatement* stmt) { | 208 void VisitReturnStatement(ReturnStatement* stmt) { |
| 225 if (in_function_) { | 209 if (scope_ == kModuleScope) { |
| 210 scope_ = kExportScope; | |
| 211 RECURSE(Visit(stmt->expression())); | |
| 212 scope_ = kModuleScope; | |
| 213 } else if (scope_ == kFuncScope) { | |
| 214 RECURSE(Visit(stmt->expression())); | |
| 226 current_function_builder_->Emit(kExprReturn); | 215 current_function_builder_->Emit(kExprReturn); |
| 227 } else { | 216 } else { |
| 228 marking_exported = true; | 217 UNREACHABLE(); |
| 229 } | |
| 230 RECURSE(Visit(stmt->expression())); | |
| 231 if (!in_function_) { | |
| 232 marking_exported = false; | |
| 233 } | 218 } |
| 234 } | 219 } |
| 235 | 220 |
| 236 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } | 221 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } |
| 237 | 222 |
| 238 void SetLocalTo(uint16_t index, int value) { | 223 void SetLocalTo(uint16_t index, int32_t value) { |
| 224 current_function_builder_->EmitI32Const(value); | |
| 239 current_function_builder_->Emit(kExprSetLocal); | 225 current_function_builder_->Emit(kExprSetLocal); |
| 240 AddLeb128(index, true); | 226 AddLeb128(index, true); |
| 241 // TODO(bradnelson): variable size | |
| 242 byte code[] = {WASM_I32V(value)}; | |
| 243 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 244 block_size_++; | |
| 245 } | 227 } |
| 246 | 228 |
| 247 void CompileCase(CaseClause* clause, uint16_t fall_through, | 229 void CompileCase(CaseClause* clause, uint16_t fall_through, |
| 248 VariableProxy* tag) { | 230 VariableProxy* tag) { |
| 249 Literal* label = clause->label()->AsLiteral(); | 231 Literal* label = clause->label()->AsLiteral(); |
| 250 DCHECK_NOT_NULL(label); | 232 DCHECK_NOT_NULL(label); |
| 251 block_size_++; | |
| 252 current_function_builder_->Emit(kExprIf); | |
| 253 current_function_builder_->Emit(kExprI32Ior); | |
| 254 current_function_builder_->Emit(kExprI32Eq); | |
| 255 VisitVariableProxy(tag); | 233 VisitVariableProxy(tag); |
| 256 VisitLiteral(label); | 234 VisitLiteral(label); |
| 235 current_function_builder_->Emit(kExprI32Eq); | |
| 257 current_function_builder_->Emit(kExprGetLocal); | 236 current_function_builder_->Emit(kExprGetLocal); |
| 258 AddLeb128(fall_through, true); | 237 AddLeb128(fall_through, true); |
| 259 BlockVisitor visitor(this, nullptr, kExprBlock, false, 0); | 238 current_function_builder_->Emit(kExprI32Ior); |
| 239 current_function_builder_->Emit(kExprIf); | |
| 240 BlockVisitor visitor(this, nullptr, kExprBlock, false); | |
| 260 SetLocalTo(fall_through, 1); | 241 SetLocalTo(fall_through, 1); |
| 261 ZoneList<Statement*>* stmts = clause->statements(); | 242 ZoneList<Statement*>* stmts = clause->statements(); |
| 262 block_size_ += stmts->length(); | |
| 263 RECURSE(VisitStatements(stmts)); | 243 RECURSE(VisitStatements(stmts)); |
| 244 current_function_builder_->Emit(kExprEnd); | |
| 264 } | 245 } |
| 265 | 246 |
| 266 void VisitSwitchStatement(SwitchStatement* stmt) { | 247 void VisitSwitchStatement(SwitchStatement* stmt) { |
| 267 VariableProxy* tag = stmt->tag()->AsVariableProxy(); | 248 VariableProxy* tag = stmt->tag()->AsVariableProxy(); |
| 268 DCHECK_NOT_NULL(tag); | 249 DCHECK_NOT_NULL(tag); |
| 269 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false, | 250 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false); |
| 270 0); | |
| 271 uint16_t fall_through = current_function_builder_->AddLocal(kAstI32); | 251 uint16_t fall_through = current_function_builder_->AddLocal(kAstI32); |
| 272 SetLocalTo(fall_through, 0); | 252 SetLocalTo(fall_through, 0); |
| 273 | 253 |
| 274 ZoneList<CaseClause*>* clauses = stmt->cases(); | 254 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 275 for (int i = 0; i < clauses->length(); ++i) { | 255 for (int i = 0; i < clauses->length(); ++i) { |
| 276 CaseClause* clause = clauses->at(i); | 256 CaseClause* clause = clauses->at(i); |
| 277 if (!clause->is_default()) { | 257 if (!clause->is_default()) { |
| 278 CompileCase(clause, fall_through, tag); | 258 CompileCase(clause, fall_through, tag); |
| 279 } else { | 259 } else { |
| 280 ZoneList<Statement*>* stmts = clause->statements(); | 260 ZoneList<Statement*>* stmts = clause->statements(); |
| 281 block_size_ += stmts->length(); | |
| 282 RECURSE(VisitStatements(stmts)); | 261 RECURSE(VisitStatements(stmts)); |
| 283 } | 262 } |
| 284 } | 263 } |
| 285 } | 264 } |
| 286 | 265 |
| 287 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 266 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |
| 288 | 267 |
| 289 void VisitDoWhileStatement(DoWhileStatement* stmt) { | 268 void VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 290 DCHECK(in_function_); | 269 DCHECK_EQ(kFuncScope, scope_); |
| 291 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 270 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
| 292 2); | |
| 293 RECURSE(Visit(stmt->body())); | 271 RECURSE(Visit(stmt->body())); |
| 272 RECURSE(Visit(stmt->cond())); | |
| 294 current_function_builder_->Emit(kExprIf); | 273 current_function_builder_->Emit(kExprIf); |
| 295 RECURSE(Visit(stmt->cond())); | 274 current_function_builder_->EmitWithU8(kExprBr, 0); |
| 296 current_function_builder_->EmitWithVarInt(kExprBr, 0); | 275 current_function_builder_->Emit(kExprEnd); |
| 297 current_function_builder_->Emit(kExprNop); | |
| 298 } | 276 } |
| 299 | 277 |
| 300 void VisitWhileStatement(WhileStatement* stmt) { | 278 void VisitWhileStatement(WhileStatement* stmt) { |
| 301 DCHECK(in_function_); | 279 DCHECK_EQ(kFuncScope, scope_); |
| 302 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 280 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
| 303 1); | 281 RECURSE(Visit(stmt->cond())); |
| 304 current_function_builder_->Emit(kExprIf); | 282 current_function_builder_->Emit(kExprIf); |
| 305 RECURSE(Visit(stmt->cond())); | |
| 306 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
| 307 RECURSE(Visit(stmt->body())); | 283 RECURSE(Visit(stmt->body())); |
| 284 current_function_builder_->EmitWithU8(kExprBr, 0); | |
| 285 current_function_builder_->Emit(kExprEnd); | |
| 308 } | 286 } |
| 309 | 287 |
| 310 void VisitForStatement(ForStatement* stmt) { | 288 void VisitForStatement(ForStatement* stmt) { |
| 311 DCHECK(in_function_); | 289 DCHECK_EQ(kFuncScope, scope_); |
| 312 if (stmt->init() != nullptr) { | 290 if (stmt->init() != nullptr) { |
| 313 block_size_++; | |
| 314 RECURSE(Visit(stmt->init())); | 291 RECURSE(Visit(stmt->init())); |
| 315 } | 292 } |
| 316 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 293 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
| 317 0); | |
| 318 if (stmt->cond() != nullptr) { | 294 if (stmt->cond() != nullptr) { |
| 319 block_size_++; | 295 RECURSE(Visit(stmt->cond())); |
| 296 current_function_builder_->Emit(kExprI32Eqz); | |
| 320 current_function_builder_->Emit(kExprIf); | 297 current_function_builder_->Emit(kExprIf); |
| 321 current_function_builder_->Emit(kExprI32Eqz); | |
| 322 RECURSE(Visit(stmt->cond())); | |
| 323 current_function_builder_->EmitWithVarInt(kExprBr, 1); | |
| 324 current_function_builder_->Emit(kExprNop); | 298 current_function_builder_->Emit(kExprNop); |
| 299 current_function_builder_->EmitWithU8(kExprBr, 1); | |
| 300 current_function_builder_->Emit(kExprEnd); | |
| 325 } | 301 } |
| 326 if (stmt->body() != nullptr) { | 302 if (stmt->body() != nullptr) { |
| 327 block_size_++; | |
| 328 RECURSE(Visit(stmt->body())); | 303 RECURSE(Visit(stmt->body())); |
| 329 } | 304 } |
| 330 if (stmt->next() != nullptr) { | 305 if (stmt->next() != nullptr) { |
| 331 block_size_++; | |
| 332 RECURSE(Visit(stmt->next())); | 306 RECURSE(Visit(stmt->next())); |
| 333 } | 307 } |
| 334 block_size_++; | |
| 335 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
| 336 current_function_builder_->Emit(kExprNop); | 308 current_function_builder_->Emit(kExprNop); |
| 309 current_function_builder_->EmitWithU8(kExprBr, 0); | |
| 337 } | 310 } |
| 338 | 311 |
| 339 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } | 312 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } |
| 340 | 313 |
| 341 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } | 314 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } |
| 342 | 315 |
| 343 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } | 316 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } |
| 344 | 317 |
| 345 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } | 318 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } |
| 346 | 319 |
| 347 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } | 320 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } |
| 348 | 321 |
| 349 void VisitFunctionLiteral(FunctionLiteral* expr) { | 322 void VisitFunctionLiteral(FunctionLiteral* expr) { |
| 350 Scope* scope = expr->scope(); | 323 Scope* scope = expr->scope(); |
| 351 if (in_function_) { | 324 if (scope_ == kFuncScope) { |
| 352 if (expr->bounds().lower->IsFunction()) { | 325 if (expr->bounds().lower->IsFunction()) { |
| 353 FunctionType* func_type = expr->bounds().lower->AsFunction(); | 326 FunctionType* func_type = expr->bounds().lower->AsFunction(); |
| 354 LocalType return_type = TypeFrom(func_type->Result()); | 327 LocalType return_type = TypeFrom(func_type->Result()); |
| 355 current_function_builder_->ReturnType(return_type); | 328 current_function_builder_->ReturnType(return_type); |
| 356 for (int i = 0; i < expr->parameter_count(); i++) { | 329 for (int i = 0; i < expr->parameter_count(); i++) { |
| 357 LocalType type = TypeFrom(func_type->Parameter(i)); | 330 LocalType type = TypeFrom(func_type->Parameter(i)); |
| 358 DCHECK_NE(kAstStmt, type); | 331 DCHECK_NE(kAstStmt, type); |
| 359 LookupOrInsertLocal(scope->parameter(i), type); | 332 LookupOrInsertLocal(scope->parameter(i), type); |
| 360 } | 333 } |
| 361 } else { | 334 } else { |
| 362 UNREACHABLE(); | 335 UNREACHABLE(); |
| 363 } | 336 } |
| 364 } | 337 } |
| 365 RECURSE(VisitStatements(expr->body())); | 338 RECURSE(VisitStatements(expr->body())); |
| 366 RECURSE(VisitDeclarations(scope->declarations())); | 339 RECURSE(VisitDeclarations(scope->declarations())); |
| 367 } | 340 } |
| 368 | 341 |
| 369 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 342 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 370 UNREACHABLE(); | 343 UNREACHABLE(); |
| 371 } | 344 } |
| 372 | 345 |
| 373 void VisitConditional(Conditional* expr) { | 346 void VisitConditional(Conditional* expr) { |
| 374 DCHECK(in_function_); | 347 DCHECK_EQ(kFuncScope, scope_); |
| 375 current_function_builder_->Emit(kExprIfElse); | |
| 376 RECURSE(Visit(expr->condition())); | 348 RECURSE(Visit(expr->condition())); |
| 349 current_function_builder_->Emit(kExprIf); | |
| 377 RECURSE(Visit(expr->then_expression())); | 350 RECURSE(Visit(expr->then_expression())); |
| 351 current_function_builder_->Emit(kExprElse); | |
| 378 RECURSE(Visit(expr->else_expression())); | 352 RECURSE(Visit(expr->else_expression())); |
| 353 current_function_builder_->Emit(kExprEnd); | |
| 379 } | 354 } |
| 380 | 355 |
| 381 bool VisitStdlibConstant(Variable* var) { | 356 bool VisitStdlibConstant(Variable* var) { |
| 382 AsmTyper::StandardMember standard_object = | 357 AsmTyper::StandardMember standard_object = |
| 383 typer_->VariableAsStandardMember(var); | 358 typer_->VariableAsStandardMember(var); |
| 384 double value; | 359 double value; |
| 385 switch (standard_object) { | 360 switch (standard_object) { |
| 386 case AsmTyper::kInfinity: { | 361 case AsmTyper::kInfinity: { |
| 387 value = std::numeric_limits<double>::infinity(); | 362 value = std::numeric_limits<double>::infinity(); |
| 388 break; | 363 break; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 424 break; | 399 break; |
| 425 } | 400 } |
| 426 default: { return false; } | 401 default: { return false; } |
| 427 } | 402 } |
| 428 byte code[] = {WASM_F64(value)}; | 403 byte code[] = {WASM_F64(value)}; |
| 429 current_function_builder_->EmitCode(code, sizeof(code)); | 404 current_function_builder_->EmitCode(code, sizeof(code)); |
| 430 return true; | 405 return true; |
| 431 } | 406 } |
| 432 | 407 |
| 433 void VisitVariableProxy(VariableProxy* expr) { | 408 void VisitVariableProxy(VariableProxy* expr) { |
| 434 if (in_function_) { | 409 if (scope_ == kFuncScope || scope_ == kInitScope) { |
| 435 Variable* var = expr->var(); | 410 Variable* var = expr->var(); |
| 436 if (is_set_op_) { | 411 if (VisitStdlibConstant(var)) { |
| 437 if (var->IsContextSlot()) { | 412 return; |
| 438 current_function_builder_->Emit(kExprStoreGlobal); | |
| 439 } else { | |
| 440 current_function_builder_->Emit(kExprSetLocal); | |
| 441 } | |
| 442 is_set_op_ = false; | |
| 443 } else { | |
| 444 if (VisitStdlibConstant(var)) { | |
| 445 return; | |
| 446 } | |
| 447 if (var->IsContextSlot()) { | |
| 448 current_function_builder_->Emit(kExprLoadGlobal); | |
| 449 } else { | |
| 450 current_function_builder_->Emit(kExprGetLocal); | |
| 451 } | |
| 452 } | 413 } |
| 453 LocalType var_type = TypeOf(expr); | 414 LocalType var_type = TypeOf(expr); |
| 454 DCHECK_NE(kAstStmt, var_type); | 415 DCHECK_NE(kAstStmt, var_type); |
| 455 if (var->IsContextSlot()) { | 416 if (var->IsContextSlot()) { |
| 417 current_function_builder_->Emit(kExprLoadGlobal); | |
| 456 AddLeb128(LookupOrInsertGlobal(var, var_type), false); | 418 AddLeb128(LookupOrInsertGlobal(var, var_type), false); |
| 457 } else { | 419 } else { |
| 420 current_function_builder_->Emit(kExprGetLocal); | |
| 458 AddLeb128(LookupOrInsertLocal(var, var_type), true); | 421 AddLeb128(LookupOrInsertLocal(var, var_type), true); |
| 459 } | 422 } |
| 460 } | 423 } |
| 461 } | 424 } |
| 462 | 425 |
| 463 void VisitLiteral(Literal* expr) { | 426 void VisitLiteral(Literal* expr) { |
| 464 if (in_function_) { | 427 if (scope_ == kFuncScope || scope_ == kInitScope) { |
| 465 if (expr->raw_value()->IsNumber()) { | 428 if (expr->raw_value()->IsNumber()) { |
| 466 LocalType type = TypeOf(expr); | 429 LocalType type = TypeOf(expr); |
| 467 switch (type) { | 430 switch (type) { |
| 468 case kAstI32: { | 431 case kAstI32: { |
| 469 int val = static_cast<int>(expr->raw_value()->AsNumber()); | 432 int32_t val = static_cast<int32_t>(expr->raw_value()->AsNumber()); |
| 470 // TODO(bradnelson): variable size | 433 current_function_builder_->EmitI32Const(val); |
| 471 byte code[] = {WASM_I32V(val)}; | |
| 472 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 473 break; | 434 break; |
| 474 } | 435 } |
| 475 case kAstF32: { | 436 case kAstF32: { |
| 476 float val = static_cast<float>(expr->raw_value()->AsNumber()); | 437 float val = static_cast<float>(expr->raw_value()->AsNumber()); |
| 477 byte code[] = {WASM_F32(val)}; | 438 byte code[] = {WASM_F32(val)}; |
| 478 current_function_builder_->EmitCode(code, sizeof(code)); | 439 current_function_builder_->EmitCode(code, sizeof(code)); |
| 479 break; | 440 break; |
| 480 } | 441 } |
| 481 case kAstF64: { | 442 case kAstF64: { |
| 482 double val = static_cast<double>(expr->raw_value()->AsNumber()); | 443 double val = static_cast<double>(expr->raw_value()->AsNumber()); |
| 483 byte code[] = {WASM_F64(val)}; | 444 byte code[] = {WASM_F64(val)}; |
| 484 current_function_builder_->EmitCode(code, sizeof(code)); | 445 current_function_builder_->EmitCode(code, sizeof(code)); |
| 485 break; | 446 break; |
| 486 } | 447 } |
| 487 default: | 448 default: |
| 488 UNREACHABLE(); | 449 UNREACHABLE(); |
| 489 } | 450 } |
| 490 } | 451 } |
| 491 } | 452 } |
| 492 } | 453 } |
| 493 | 454 |
| 494 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } | 455 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } |
| 495 | 456 |
| 496 void VisitObjectLiteral(ObjectLiteral* expr) { | 457 void VisitObjectLiteral(ObjectLiteral* expr) { |
| 497 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | 458 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
| 498 for (int i = 0; i < props->length(); ++i) { | 459 for (int i = 0; i < props->length(); ++i) { |
| 499 ObjectLiteralProperty* prop = props->at(i); | 460 ObjectLiteralProperty* prop = props->at(i); |
| 500 DCHECK(marking_exported); | 461 DCHECK_EQ(kExportScope, scope_); |
| 501 VariableProxy* expr = prop->value()->AsVariableProxy(); | 462 VariableProxy* expr = prop->value()->AsVariableProxy(); |
| 502 DCHECK_NOT_NULL(expr); | 463 DCHECK_NOT_NULL(expr); |
| 503 Variable* var = expr->var(); | 464 Variable* var = expr->var(); |
| 504 Literal* name = prop->key()->AsLiteral(); | 465 Literal* name = prop->key()->AsLiteral(); |
| 505 DCHECK_NOT_NULL(name); | 466 DCHECK_NOT_NULL(name); |
| 506 DCHECK(name->IsPropertyName()); | 467 DCHECK(name->IsPropertyName()); |
| 507 const AstRawString* raw_name = name->AsRawPropertyName(); | 468 const AstRawString* raw_name = name->AsRawPropertyName(); |
| 508 if (var->is_function()) { | 469 if (var->is_function()) { |
| 509 uint16_t index = LookupOrInsertFunction(var); | 470 uint16_t index = LookupOrInsertFunction(var); |
| 510 builder_->FunctionAt(index)->Exported(1); | 471 builder_->FunctionAt(index)->Exported(1); |
| 511 builder_->FunctionAt(index) | 472 builder_->FunctionAt(index) |
| 512 ->SetName(raw_name->raw_data(), raw_name->length()); | 473 ->SetName(raw_name->raw_data(), raw_name->length()); |
| 513 } | 474 } |
| 514 } | 475 } |
| 515 } | 476 } |
| 516 | 477 |
| 517 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } | 478 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } |
| 518 | 479 |
| 519 void LoadInitFunction() { | 480 void LoadInitFunction() { |
| 520 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 481 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 521 in_function_ = true; | 482 scope_ = kInitScope; |
| 522 } | 483 } |
| 523 | 484 |
| 524 void UnLoadInitFunction() { | 485 void UnLoadInitFunction() { |
| 525 in_function_ = false; | 486 scope_ = kModuleScope; |
| 526 current_function_builder_ = nullptr; | 487 current_function_builder_ = nullptr; |
| 527 } | 488 } |
| 528 | 489 |
| 529 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 490 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
| 530 FunctionType* func_type = | 491 FunctionType* func_type = |
| 531 funcs->bounds().lower->AsArray()->Element()->AsFunction(); | 492 funcs->bounds().lower->AsArray()->Element()->AsFunction(); |
| 532 LocalType return_type = TypeFrom(func_type->Result()); | 493 LocalType return_type = TypeFrom(func_type->Result()); |
| 533 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 494 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 534 func_type->Arity()); | 495 func_type->Arity()); |
| 535 if (return_type != kAstStmt) { | 496 if (return_type != kAstStmt) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 618 function->ReturnType(sig->GetReturn()); | 579 function->ReturnType(sig->GetReturn()); |
| 619 } | 580 } |
| 620 for (size_t i = 0; i < sig->parameter_count(); i++) { | 581 for (size_t i = 0; i < sig->parameter_count(); i++) { |
| 621 function->AddParam(sig->GetParam(i)); | 582 function->AddParam(sig->GetParam(i)); |
| 622 } | 583 } |
| 623 return index; | 584 return index; |
| 624 } | 585 } |
| 625 } | 586 } |
| 626 }; | 587 }; |
| 627 | 588 |
| 628 void VisitAssignment(Assignment* expr) { | 589 void EmitAssignmentLhs(Expression* target, MachineType* mtype) { |
| 629 bool in_init = false; | 590 // Match the left hand side of the assignment. |
| 630 if (!in_function_) { | 591 VariableProxy* target_var = target->AsVariableProxy(); |
| 631 BinaryOperation* binop = expr->value()->AsBinaryOperation(); | 592 if (target_var != nullptr) { |
| 632 if (binop != nullptr) { | 593 // Left hand side is a local or a global variable, no code on LHS. |
| 594 return; | |
| 595 } | |
| 596 | |
| 597 Property* target_prop = target->AsProperty(); | |
| 598 if (target_prop != nullptr) { | |
| 599 // Left hand side is a property access, i.e. the asm.js heap. | |
| 600 VisitPropertyAndEmitIndex(target_prop, mtype); | |
| 601 return; | |
| 602 } | |
| 603 | |
| 604 if (target_var == nullptr && target_prop == nullptr) { | |
|
bradnelson
2016/03/23 19:14:25
You return above, why guard this, as you return in
titzer
2016/03/23 19:53:05
Because paranoia :-)
bradn
2016/03/23 19:58:50
Seems like leaving the UNREACHABLE unguarded would
| |
| 605 UNREACHABLE(); // invalid assignment. | |
| 606 } | |
| 607 } | |
| 608 | |
| 609 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { | |
| 610 BinaryOperation* binop = value->AsBinaryOperation(); | |
| 611 if (binop != nullptr) { | |
| 612 if (scope_ == kInitScope) { | |
| 613 // Handle foreign variables in the initialization scope. | |
| 633 Property* prop = binop->left()->AsProperty(); | 614 Property* prop = binop->left()->AsProperty(); |
| 634 DCHECK_NOT_NULL(prop); | |
| 635 LoadInitFunction(); | |
| 636 is_set_op_ = true; | |
| 637 RECURSE(Visit(expr->target())); | |
| 638 DCHECK(!is_set_op_); | |
| 639 if (binop->op() == Token::MUL) { | 615 if (binop->op() == Token::MUL) { |
| 640 DCHECK(binop->right()->IsLiteral()); | 616 DCHECK(binop->right()->IsLiteral()); |
| 641 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 617 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
| 642 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 618 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
| 643 VisitForeignVariable(true, prop); | 619 VisitForeignVariable(true, prop); |
| 620 return; | |
| 644 } else if (binop->op() == Token::BIT_OR) { | 621 } else if (binop->op() == Token::BIT_OR) { |
| 645 DCHECK(binop->right()->IsLiteral()); | 622 DCHECK(binop->right()->IsLiteral()); |
| 646 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 623 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
| 647 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 624 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
| 648 VisitForeignVariable(false, prop); | 625 VisitForeignVariable(false, prop); |
| 626 return; | |
| 649 } else { | 627 } else { |
| 650 UNREACHABLE(); | 628 UNREACHABLE(); |
| 651 } | 629 } |
| 652 UnLoadInitFunction(); | |
| 653 return; | |
| 654 } | 630 } |
| 631 if (MatchBinaryOperation(binop) == kAsIs) { | |
| 632 VariableProxy* target_var = target->AsVariableProxy(); | |
| 633 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy(); | |
| 634 if (target_var != nullptr && effective_value_var != nullptr && | |
| 635 target_var->var() == effective_value_var->var()) { | |
| 636 *is_nop = true; | |
| 637 return; | |
| 638 } | |
| 639 } | |
| 640 } | |
| 641 RECURSE(Visit(value)); | |
| 642 } | |
| 643 | |
| 644 void EmitAssignment(Assignment* expr, MachineType mtype) { | |
| 645 // Match the left hand side of the assignment. | |
| 646 VariableProxy* target_var = expr->target()->AsVariableProxy(); | |
| 647 if (target_var != nullptr) { | |
| 648 // Left hand side is a local or a global variable. | |
| 649 Variable* var = target_var->var(); | |
| 650 LocalType var_type = TypeOf(expr); | |
| 651 DCHECK_NE(kAstStmt, var_type); | |
| 652 if (var->IsContextSlot()) { | |
| 653 current_function_builder_->Emit(kExprStoreGlobal); | |
| 654 AddLeb128(LookupOrInsertGlobal(var, var_type), false); | |
| 655 } else { | |
| 656 current_function_builder_->Emit(kExprSetLocal); | |
| 657 AddLeb128(LookupOrInsertLocal(var, var_type), true); | |
| 658 } | |
| 659 } | |
| 660 | |
| 661 Property* target_prop = expr->target()->AsProperty(); | |
| 662 if (target_prop != nullptr) { | |
| 663 // Left hand side is a property access, i.e. the asm.js heap. | |
| 664 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | |
| 665 expr->target()->AsProperty()->obj()->bounds().lower->Is( | |
| 666 cache_.kFloat32Array)) { | |
| 667 current_function_builder_->Emit(kExprF32ConvertF64); | |
| 668 } | |
| 669 current_function_builder_->EmitWithU8U8( | |
| 670 WasmOpcodes::LoadStoreOpcodeOf(mtype, true), 0, 0); | |
| 671 } | |
| 672 | |
| 673 if (target_var == nullptr && target_prop == nullptr) { | |
|
bradnelson
2016/03/23 19:14:25
Add returns instead of guard here?
titzer
2016/03/23 19:53:05
Don't want to silently forget to generate code.
| |
| 674 UNREACHABLE(); // invalid assignment. | |
| 675 } | |
| 676 } | |
| 677 | |
| 678 void VisitAssignment(Assignment* expr) { | |
| 679 bool as_init = false; | |
| 680 if (scope_ == kModuleScope) { | |
| 655 Property* prop = expr->value()->AsProperty(); | 681 Property* prop = expr->value()->AsProperty(); |
| 656 if (prop != nullptr) { | 682 if (prop != nullptr) { |
| 657 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 683 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
| 658 if (vp != nullptr && vp->var()->IsParameter() && | 684 if (vp != nullptr && vp->var()->IsParameter() && |
| 659 vp->var()->index() == 1) { | 685 vp->var()->index() == 1) { |
| 660 VariableProxy* target = expr->target()->AsVariableProxy(); | 686 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 661 if (target->bounds().lower->Is(Type::Function())) { | 687 if (target->bounds().lower->Is(Type::Function())) { |
| 662 const AstRawString* name = | 688 const AstRawString* name = |
| 663 prop->key()->AsLiteral()->AsRawPropertyName(); | 689 prop->key()->AsLiteral()->AsRawPropertyName(); |
| 664 imported_function_table_.AddImport(target->var(), name->raw_data(), | 690 imported_function_table_.AddImport(target->var(), name->raw_data(), |
| 665 name->length()); | 691 name->length()); |
| 666 } | 692 } |
| 667 } | 693 } |
| 668 // Property values in module scope don't emit code, so return. | 694 // Property values in module scope don't emit code, so return. |
| 669 return; | 695 return; |
| 670 } | 696 } |
| 671 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 697 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| 672 if (funcs != nullptr && | 698 if (funcs != nullptr && |
| 673 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { | 699 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { |
| 674 VariableProxy* target = expr->target()->AsVariableProxy(); | 700 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 675 DCHECK_NOT_NULL(target); | 701 DCHECK_NOT_NULL(target); |
| 676 AddFunctionTable(target, funcs); | 702 AddFunctionTable(target, funcs); |
| 677 // Only add to the function table. No init needed. | 703 // Only add to the function table. No init needed. |
| 678 return; | 704 return; |
| 679 } | 705 } |
| 680 if (expr->value()->IsCallNew()) { | 706 if (expr->value()->IsCallNew()) { |
| 681 // No init code to emit for CallNew nodes. | 707 // No init code to emit for CallNew nodes. |
| 682 return; | 708 return; |
| 683 } | 709 } |
| 684 in_init = true; | 710 as_init = true; |
| 685 LoadInitFunction(); | |
| 686 } | 711 } |
| 687 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); | 712 |
| 688 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { | 713 if (as_init) LoadInitFunction(); |
| 689 VariableProxy* target_var = expr->target()->AsVariableProxy(); | 714 MachineType mtype; |
| 690 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); | 715 bool is_nop = false; |
| 691 if (target_var != nullptr && effective_value_var != nullptr && | 716 EmitAssignmentLhs(expr->target(), &mtype); |
| 692 target_var->var() == effective_value_var->var()) { | 717 EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); |
| 693 block_size_--; | 718 if (!is_nop) { |
| 694 return; | 719 EmitAssignment(expr, mtype); |
| 695 } | |
| 696 } | 720 } |
| 697 is_set_op_ = true; | 721 if (as_init) UnLoadInitFunction(); |
| 698 RECURSE(Visit(expr->target())); | |
| 699 DCHECK(!is_set_op_); | |
| 700 // Assignment to heapf32 from float64 converts. | |
| 701 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | |
| 702 expr->target()->AsProperty()->obj()->bounds().lower->Is( | |
| 703 cache_.kFloat32Array)) { | |
| 704 current_function_builder_->Emit(kExprF32ConvertF64); | |
| 705 } | |
| 706 RECURSE(Visit(expr->value())); | |
| 707 if (in_init) { | |
| 708 UnLoadInitFunction(); | |
| 709 } | |
| 710 } | 722 } |
| 711 | 723 |
| 712 void VisitYield(Yield* expr) { UNREACHABLE(); } | 724 void VisitYield(Yield* expr) { UNREACHABLE(); } |
| 713 | 725 |
| 714 void VisitThrow(Throw* expr) { UNREACHABLE(); } | 726 void VisitThrow(Throw* expr) { UNREACHABLE(); } |
| 715 | 727 |
| 716 void VisitForeignVariable(bool is_float, Property* expr) { | 728 void VisitForeignVariable(bool is_float, Property* expr) { |
| 717 DCHECK(expr->obj()->AsVariableProxy()); | 729 DCHECK(expr->obj()->AsVariableProxy()); |
| 718 DCHECK(VariableLocation::PARAMETER == | 730 DCHECK(VariableLocation::PARAMETER == |
| 719 expr->obj()->AsVariableProxy()->var()->location()); | 731 expr->obj()->AsVariableProxy()->var()->location()); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 738 return; | 750 return; |
| 739 } | 751 } |
| 740 } | 752 } |
| 741 } else { | 753 } else { |
| 742 MaybeHandle<Object> maybe_nvalue = | 754 MaybeHandle<Object> maybe_nvalue = |
| 743 i::Object::ToInt32(isolate_, value); | 755 i::Object::ToInt32(isolate_, value); |
| 744 if (!maybe_nvalue.is_null()) { | 756 if (!maybe_nvalue.is_null()) { |
| 745 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); | 757 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); |
| 746 if (nvalue->IsNumber()) { | 758 if (nvalue->IsNumber()) { |
| 747 int32_t val = static_cast<int32_t>(nvalue->Number()); | 759 int32_t val = static_cast<int32_t>(nvalue->Number()); |
| 748 // TODO(bradnelson): variable size | 760 current_function_builder_->EmitI32Const(val); |
| 749 byte code[] = {WASM_I32V(val)}; | |
| 750 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 751 return; | 761 return; |
| 752 } | 762 } |
| 753 } | 763 } |
| 754 } | 764 } |
| 755 } | 765 } |
| 756 } | 766 } |
| 757 if (is_float) { | 767 if (is_float) { |
| 758 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; | 768 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; |
| 759 current_function_builder_->EmitCode(code, sizeof(code)); | 769 current_function_builder_->EmitCode(code, sizeof(code)); |
| 760 } else { | 770 } else { |
| 761 byte code[] = {WASM_I32V_1(0)}; | 771 byte code[] = {WASM_I32V_1(0)}; |
| 762 current_function_builder_->EmitCode(code, sizeof(code)); | 772 current_function_builder_->EmitCode(code, sizeof(code)); |
| 763 } | 773 } |
| 764 } | 774 } |
| 765 | 775 |
| 766 void VisitProperty(Property* expr) { | 776 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { |
| 767 Expression* obj = expr->obj(); | 777 Expression* obj = expr->obj(); |
| 768 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); | 778 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); |
| 769 Type* type = obj->bounds().lower; | 779 Type* type = obj->bounds().lower; |
| 770 MachineType mtype; | |
| 771 int size; | 780 int size; |
| 772 if (type->Is(cache_.kUint8Array)) { | 781 if (type->Is(cache_.kUint8Array)) { |
| 773 mtype = MachineType::Uint8(); | 782 *mtype = MachineType::Uint8(); |
| 774 size = 1; | 783 size = 1; |
| 775 } else if (type->Is(cache_.kInt8Array)) { | 784 } else if (type->Is(cache_.kInt8Array)) { |
| 776 mtype = MachineType::Int8(); | 785 *mtype = MachineType::Int8(); |
| 777 size = 1; | 786 size = 1; |
| 778 } else if (type->Is(cache_.kUint16Array)) { | 787 } else if (type->Is(cache_.kUint16Array)) { |
| 779 mtype = MachineType::Uint16(); | 788 *mtype = MachineType::Uint16(); |
| 780 size = 2; | 789 size = 2; |
| 781 } else if (type->Is(cache_.kInt16Array)) { | 790 } else if (type->Is(cache_.kInt16Array)) { |
| 782 mtype = MachineType::Int16(); | 791 *mtype = MachineType::Int16(); |
| 783 size = 2; | 792 size = 2; |
| 784 } else if (type->Is(cache_.kUint32Array)) { | 793 } else if (type->Is(cache_.kUint32Array)) { |
| 785 mtype = MachineType::Uint32(); | 794 *mtype = MachineType::Uint32(); |
| 786 size = 4; | 795 size = 4; |
| 787 } else if (type->Is(cache_.kInt32Array)) { | 796 } else if (type->Is(cache_.kInt32Array)) { |
| 788 mtype = MachineType::Int32(); | 797 *mtype = MachineType::Int32(); |
| 789 size = 4; | 798 size = 4; |
| 790 } else if (type->Is(cache_.kUint32Array)) { | 799 } else if (type->Is(cache_.kUint32Array)) { |
| 791 mtype = MachineType::Uint32(); | 800 *mtype = MachineType::Uint32(); |
| 792 size = 4; | 801 size = 4; |
| 793 } else if (type->Is(cache_.kFloat32Array)) { | 802 } else if (type->Is(cache_.kFloat32Array)) { |
| 794 mtype = MachineType::Float32(); | 803 *mtype = MachineType::Float32(); |
| 795 size = 4; | 804 size = 4; |
| 796 } else if (type->Is(cache_.kFloat64Array)) { | 805 } else if (type->Is(cache_.kFloat64Array)) { |
| 797 mtype = MachineType::Float64(); | 806 *mtype = MachineType::Float64(); |
| 798 size = 8; | 807 size = 8; |
| 799 } else { | 808 } else { |
| 800 UNREACHABLE(); | 809 UNREACHABLE(); |
| 801 } | 810 } |
| 802 // TODO(titzer): use special asm-compatibility opcodes? | |
| 803 current_function_builder_->EmitWithU8U8( | |
| 804 WasmOpcodes::LoadStoreOpcodeOf(mtype, is_set_op_), 0, 0); | |
| 805 is_set_op_ = false; | |
| 806 if (size == 1) { | 811 if (size == 1) { |
| 807 // Allow more general expression in byte arrays than the spec | 812 // Allow more general expression in byte arrays than the spec |
| 808 // strictly permits. | 813 // strictly permits. |
| 809 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in | 814 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in |
| 810 // places that strictly should be HEAP8[HEAP32[..]>>0]. | 815 // places that strictly should be HEAP8[HEAP32[..]>>0]. |
| 811 RECURSE(Visit(expr->key())); | 816 RECURSE(Visit(expr->key())); |
| 812 return; | 817 return; |
| 813 } else { | 818 } |
| 814 Literal* value = expr->key()->AsLiteral(); | 819 |
| 815 if (value) { | 820 Literal* value = expr->key()->AsLiteral(); |
| 816 DCHECK(value->raw_value()->IsNumber()); | 821 if (value) { |
| 817 DCHECK_EQ(kAstI32, TypeOf(value)); | 822 DCHECK(value->raw_value()->IsNumber()); |
| 818 int val = static_cast<int>(value->raw_value()->AsNumber()); | 823 DCHECK_EQ(kAstI32, TypeOf(value)); |
| 819 // TODO(bradnelson): variable size | 824 int32_t val = static_cast<int32_t>(value->raw_value()->AsNumber()); |
| 820 byte code[] = {WASM_I32V(val * size)}; | 825 // TODO(titzer): handle overflow here. |
|
bradnelson
2016/03/23 19:14:25
Spec allows 0 - 2^32 -1 here. What did you mean?
titzer
2016/03/23 19:53:05
Right. If it is 2^31, e.g., and then we multiply b
bradn
2016/03/23 19:58:50
Ah, yes.
| |
| 821 current_function_builder_->EmitCode(code, sizeof(code)); | 826 current_function_builder_->EmitI32Const(val * size); |
| 822 return; | 827 return; |
| 823 } | 828 } |
| 824 BinaryOperation* binop = expr->key()->AsBinaryOperation(); | 829 BinaryOperation* binop = expr->key()->AsBinaryOperation(); |
| 825 if (binop) { | 830 if (binop) { |
| 826 DCHECK_EQ(Token::SAR, binop->op()); | 831 DCHECK_EQ(Token::SAR, binop->op()); |
| 827 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); | 832 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); |
| 828 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); | 833 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); |
| 829 DCHECK_EQ(size, | 834 DCHECK_EQ(size, |
| 830 1 << static_cast<int>( | 835 1 << static_cast<int>( |
| 831 binop->right()->AsLiteral()->raw_value()->AsNumber())); | 836 binop->right()->AsLiteral()->raw_value()->AsNumber())); |
| 832 // Mask bottom bits to match asm.js behavior. | 837 // Mask bottom bits to match asm.js behavior. |
| 833 current_function_builder_->Emit(kExprI32And); | 838 byte mask = static_cast<byte>(~(size - 1)); |
| 834 byte code[] = {WASM_I8(~(size - 1))}; | 839 RECURSE(Visit(binop->left())); |
| 835 current_function_builder_->EmitCode(code, sizeof(code)); | 840 current_function_builder_->EmitWithU8(kExprI8Const, mask); |
| 836 RECURSE(Visit(binop->left())); | 841 current_function_builder_->Emit(kExprI32And); |
| 837 return; | 842 return; |
| 838 } | |
| 839 } | 843 } |
| 840 UNREACHABLE(); | 844 UNREACHABLE(); |
| 841 } | 845 } |
| 842 | 846 |
| 847 void VisitProperty(Property* expr) { | |
| 848 MachineType mtype; | |
| 849 VisitPropertyAndEmitIndex(expr, &mtype); | |
| 850 current_function_builder_->EmitWithU8U8( | |
| 851 WasmOpcodes::LoadStoreOpcodeOf(mtype, false), 0, 0); | |
| 852 } | |
| 853 | |
| 843 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { | 854 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { |
| 844 Variable* var = expr->var(); | 855 Variable* var = expr->var(); |
| 845 AsmTyper::StandardMember standard_object = | 856 AsmTyper::StandardMember standard_object = |
| 846 typer_->VariableAsStandardMember(var); | 857 typer_->VariableAsStandardMember(var); |
| 847 ZoneList<Expression*>* args = call->arguments(); | 858 ZoneList<Expression*>* args = call->arguments(); |
| 848 LocalType call_type = TypeOf(call); | 859 LocalType call_type = TypeOf(call); |
| 860 | |
| 849 switch (standard_object) { | 861 switch (standard_object) { |
| 850 case AsmTyper::kNone: { | 862 case AsmTyper::kNone: { |
| 851 return false; | 863 return false; |
| 852 } | 864 } |
| 853 case AsmTyper::kMathAcos: { | 865 case AsmTyper::kMathAcos: { |
| 866 VisitCallArgs(call); | |
| 854 DCHECK_EQ(kAstF64, call_type); | 867 DCHECK_EQ(kAstF64, call_type); |
| 855 current_function_builder_->Emit(kExprF64Acos); | 868 current_function_builder_->Emit(kExprF64Acos); |
| 856 break; | 869 break; |
| 857 } | 870 } |
| 858 case AsmTyper::kMathAsin: { | 871 case AsmTyper::kMathAsin: { |
| 872 VisitCallArgs(call); | |
| 859 DCHECK_EQ(kAstF64, call_type); | 873 DCHECK_EQ(kAstF64, call_type); |
| 860 current_function_builder_->Emit(kExprF64Asin); | 874 current_function_builder_->Emit(kExprF64Asin); |
| 861 break; | 875 break; |
| 862 } | 876 } |
| 863 case AsmTyper::kMathAtan: { | 877 case AsmTyper::kMathAtan: { |
| 878 VisitCallArgs(call); | |
| 864 DCHECK_EQ(kAstF64, call_type); | 879 DCHECK_EQ(kAstF64, call_type); |
| 865 current_function_builder_->Emit(kExprF64Atan); | 880 current_function_builder_->Emit(kExprF64Atan); |
| 866 break; | 881 break; |
| 867 } | 882 } |
| 868 case AsmTyper::kMathCos: { | 883 case AsmTyper::kMathCos: { |
| 884 VisitCallArgs(call); | |
| 869 DCHECK_EQ(kAstF64, call_type); | 885 DCHECK_EQ(kAstF64, call_type); |
| 870 current_function_builder_->Emit(kExprF64Cos); | 886 current_function_builder_->Emit(kExprF64Cos); |
| 871 break; | 887 break; |
| 872 } | 888 } |
| 873 case AsmTyper::kMathSin: { | 889 case AsmTyper::kMathSin: { |
| 890 VisitCallArgs(call); | |
| 874 DCHECK_EQ(kAstF64, call_type); | 891 DCHECK_EQ(kAstF64, call_type); |
| 875 current_function_builder_->Emit(kExprF64Sin); | 892 current_function_builder_->Emit(kExprF64Sin); |
| 876 break; | 893 break; |
| 877 } | 894 } |
| 878 case AsmTyper::kMathTan: { | 895 case AsmTyper::kMathTan: { |
| 896 VisitCallArgs(call); | |
| 879 DCHECK_EQ(kAstF64, call_type); | 897 DCHECK_EQ(kAstF64, call_type); |
| 880 current_function_builder_->Emit(kExprF64Tan); | 898 current_function_builder_->Emit(kExprF64Tan); |
| 881 break; | 899 break; |
| 882 } | 900 } |
| 883 case AsmTyper::kMathExp: { | 901 case AsmTyper::kMathExp: { |
| 902 VisitCallArgs(call); | |
| 884 DCHECK_EQ(kAstF64, call_type); | 903 DCHECK_EQ(kAstF64, call_type); |
| 885 current_function_builder_->Emit(kExprF64Exp); | 904 current_function_builder_->Emit(kExprF64Exp); |
| 886 break; | 905 break; |
| 887 } | 906 } |
| 888 case AsmTyper::kMathLog: { | 907 case AsmTyper::kMathLog: { |
| 908 VisitCallArgs(call); | |
| 889 DCHECK_EQ(kAstF64, call_type); | 909 DCHECK_EQ(kAstF64, call_type); |
| 890 current_function_builder_->Emit(kExprF64Log); | 910 current_function_builder_->Emit(kExprF64Log); |
| 891 break; | 911 break; |
| 892 } | 912 } |
| 893 case AsmTyper::kMathCeil: { | 913 case AsmTyper::kMathCeil: { |
| 914 VisitCallArgs(call); | |
| 894 if (call_type == kAstF32) { | 915 if (call_type == kAstF32) { |
| 895 current_function_builder_->Emit(kExprF32Ceil); | 916 current_function_builder_->Emit(kExprF32Ceil); |
| 896 } else if (call_type == kAstF64) { | 917 } else if (call_type == kAstF64) { |
| 897 current_function_builder_->Emit(kExprF64Ceil); | 918 current_function_builder_->Emit(kExprF64Ceil); |
| 898 } else { | 919 } else { |
| 899 UNREACHABLE(); | 920 UNREACHABLE(); |
| 900 } | 921 } |
| 901 break; | 922 break; |
| 902 } | 923 } |
| 903 case AsmTyper::kMathFloor: { | 924 case AsmTyper::kMathFloor: { |
| 925 VisitCallArgs(call); | |
| 904 if (call_type == kAstF32) { | 926 if (call_type == kAstF32) { |
| 905 current_function_builder_->Emit(kExprF32Floor); | 927 current_function_builder_->Emit(kExprF32Floor); |
| 906 } else if (call_type == kAstF64) { | 928 } else if (call_type == kAstF64) { |
| 907 current_function_builder_->Emit(kExprF64Floor); | 929 current_function_builder_->Emit(kExprF64Floor); |
| 908 } else { | 930 } else { |
| 909 UNREACHABLE(); | 931 UNREACHABLE(); |
| 910 } | 932 } |
| 911 break; | 933 break; |
| 912 } | 934 } |
| 913 case AsmTyper::kMathSqrt: { | 935 case AsmTyper::kMathSqrt: { |
| 936 VisitCallArgs(call); | |
| 914 if (call_type == kAstF32) { | 937 if (call_type == kAstF32) { |
| 915 current_function_builder_->Emit(kExprF32Sqrt); | 938 current_function_builder_->Emit(kExprF32Sqrt); |
| 916 } else if (call_type == kAstF64) { | 939 } else if (call_type == kAstF64) { |
| 917 current_function_builder_->Emit(kExprF64Sqrt); | 940 current_function_builder_->Emit(kExprF64Sqrt); |
| 918 } else { | 941 } else { |
| 919 UNREACHABLE(); | 942 UNREACHABLE(); |
| 920 } | 943 } |
| 921 break; | 944 break; |
| 922 } | 945 } |
| 923 case AsmTyper::kMathAbs: { | 946 case AsmTyper::kMathAbs: { |
| 924 // TODO(bradnelson): Should this be cast to float? | |
| 925 if (call_type == kAstI32) { | 947 if (call_type == kAstI32) { |
| 926 current_function_builder_->Emit(kExprIfElse); | 948 uint16_t tmp = current_function_builder_->AddLocal(kAstI32); |
| 927 current_function_builder_->Emit(kExprI32LtS); | 949 |
| 928 Visit(args->at(0)); | 950 // if set_local(tmp, x) < 0 |
| 951 Visit(call->arguments()->at(0)); | |
| 952 current_function_builder_->Emit(kExprSetLocal); | |
| 953 AddLeb128(tmp, true); | |
| 929 byte code[] = {WASM_I8(0)}; | 954 byte code[] = {WASM_I8(0)}; |
| 930 current_function_builder_->EmitCode(code, sizeof(code)); | 955 current_function_builder_->EmitCode(code, sizeof(code)); |
| 956 current_function_builder_->Emit(kExprI32LtS); | |
| 957 current_function_builder_->Emit(kExprIf); | |
| 958 | |
| 959 // then (0 - tmp) | |
| 960 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 961 current_function_builder_->Emit(kExprGetLocal); | |
| 962 AddLeb128(tmp, true); | |
| 931 current_function_builder_->Emit(kExprI32Sub); | 963 current_function_builder_->Emit(kExprI32Sub); |
| 932 current_function_builder_->EmitCode(code, sizeof(code)); | 964 |
| 933 Visit(args->at(0)); | 965 // else tmp |
| 966 current_function_builder_->Emit(kExprElse); | |
| 967 current_function_builder_->Emit(kExprGetLocal); | |
| 968 AddLeb128(tmp, true); | |
| 969 // end | |
| 970 current_function_builder_->Emit(kExprEnd); | |
| 971 | |
| 934 } else if (call_type == kAstF32) { | 972 } else if (call_type == kAstF32) { |
| 973 VisitCallArgs(call); | |
| 935 current_function_builder_->Emit(kExprF32Abs); | 974 current_function_builder_->Emit(kExprF32Abs); |
| 936 } else if (call_type == kAstF64) { | 975 } else if (call_type == kAstF64) { |
| 976 VisitCallArgs(call); | |
| 937 current_function_builder_->Emit(kExprF64Abs); | 977 current_function_builder_->Emit(kExprF64Abs); |
| 938 } else { | 978 } else { |
| 939 UNREACHABLE(); | 979 UNREACHABLE(); |
| 940 } | 980 } |
| 941 break; | 981 break; |
| 942 } | 982 } |
| 943 case AsmTyper::kMathMin: { | 983 case AsmTyper::kMathMin: { |
| 944 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. | 984 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. |
| 945 if (call_type == kAstI32) { | 985 if (call_type == kAstI32) { |
| 946 current_function_builder_->Emit(kExprIfElse); | 986 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
| 987 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); | |
|
bradnelson
2016/03/23 19:14:25
Did we want to turn these into asm specific opcode
titzer
2016/03/23 19:53:05
It's probably about the same amount of work either
bradn
2016/03/23 19:58:50
K, although I still want to understand why tf call
| |
| 988 | |
| 989 // if set_local(tmp_x, x) < set_local(tmp_y, y) | |
| 990 Visit(call->arguments()->at(0)); | |
| 991 current_function_builder_->Emit(kExprSetLocal); | |
| 992 AddLeb128(tmp_x, true); | |
| 993 | |
| 994 Visit(call->arguments()->at(1)); | |
| 995 current_function_builder_->Emit(kExprSetLocal); | |
| 996 AddLeb128(tmp_y, true); | |
| 997 | |
| 947 current_function_builder_->Emit(kExprI32LeS); | 998 current_function_builder_->Emit(kExprI32LeS); |
| 948 Visit(args->at(0)); | 999 current_function_builder_->Emit(kExprIf); |
| 949 Visit(args->at(1)); | 1000 |
| 1001 // then tmp_x | |
| 1002 current_function_builder_->Emit(kExprGetLocal); | |
| 1003 AddLeb128(tmp_x, true); | |
| 1004 | |
| 1005 // else tmp_y | |
| 1006 current_function_builder_->Emit(kExprElse); | |
| 1007 current_function_builder_->Emit(kExprGetLocal); | |
| 1008 AddLeb128(tmp_y, true); | |
| 1009 current_function_builder_->Emit(kExprEnd); | |
| 1010 | |
| 950 } else if (call_type == kAstF32) { | 1011 } else if (call_type == kAstF32) { |
| 1012 VisitCallArgs(call); | |
| 951 current_function_builder_->Emit(kExprF32Min); | 1013 current_function_builder_->Emit(kExprF32Min); |
| 952 } else if (call_type == kAstF64) { | 1014 } else if (call_type == kAstF64) { |
| 1015 VisitCallArgs(call); | |
| 953 current_function_builder_->Emit(kExprF64Min); | 1016 current_function_builder_->Emit(kExprF64Min); |
| 954 } else { | 1017 } else { |
| 955 UNREACHABLE(); | 1018 UNREACHABLE(); |
| 956 } | 1019 } |
| 957 break; | 1020 break; |
| 958 } | 1021 } |
| 959 case AsmTyper::kMathMax: { | 1022 case AsmTyper::kMathMax: { |
| 960 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. | 1023 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. |
| 961 if (call_type == kAstI32) { | 1024 if (call_type == kAstI32) { |
| 962 current_function_builder_->Emit(kExprIfElse); | 1025 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
| 963 current_function_builder_->Emit(kExprI32GtS); | 1026 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); |
| 964 Visit(args->at(0)); | 1027 |
| 965 Visit(args->at(1)); | 1028 // if set_local(tmp_x, x) < set_local(tmp_y, y) |
| 1029 Visit(call->arguments()->at(0)); | |
| 1030 current_function_builder_->Emit(kExprSetLocal); | |
| 1031 AddLeb128(tmp_x, true); | |
| 1032 | |
| 1033 Visit(call->arguments()->at(1)); | |
| 1034 current_function_builder_->Emit(kExprSetLocal); | |
| 1035 AddLeb128(tmp_y, true); | |
| 1036 | |
| 1037 current_function_builder_->Emit(kExprI32LeS); | |
| 1038 current_function_builder_->Emit(kExprIf); | |
| 1039 | |
| 1040 // then tmp_y | |
| 1041 current_function_builder_->Emit(kExprGetLocal); | |
| 1042 AddLeb128(tmp_y, true); | |
| 1043 | |
| 1044 // else tmp_x | |
| 1045 current_function_builder_->Emit(kExprElse); | |
| 1046 current_function_builder_->Emit(kExprGetLocal); | |
| 1047 AddLeb128(tmp_x, true); | |
| 1048 current_function_builder_->Emit(kExprEnd); | |
| 1049 | |
| 966 } else if (call_type == kAstF32) { | 1050 } else if (call_type == kAstF32) { |
| 1051 VisitCallArgs(call); | |
| 967 current_function_builder_->Emit(kExprF32Max); | 1052 current_function_builder_->Emit(kExprF32Max); |
| 968 } else if (call_type == kAstF64) { | 1053 } else if (call_type == kAstF64) { |
| 1054 VisitCallArgs(call); | |
| 969 current_function_builder_->Emit(kExprF64Max); | 1055 current_function_builder_->Emit(kExprF64Max); |
| 970 } else { | 1056 } else { |
| 971 UNREACHABLE(); | 1057 UNREACHABLE(); |
| 972 } | 1058 } |
| 973 break; | 1059 break; |
| 974 } | 1060 } |
| 975 case AsmTyper::kMathAtan2: { | 1061 case AsmTyper::kMathAtan2: { |
| 1062 VisitCallArgs(call); | |
| 976 DCHECK_EQ(kAstF64, call_type); | 1063 DCHECK_EQ(kAstF64, call_type); |
| 977 current_function_builder_->Emit(kExprF64Atan2); | 1064 current_function_builder_->Emit(kExprF64Atan2); |
| 978 break; | 1065 break; |
| 979 } | 1066 } |
| 980 case AsmTyper::kMathPow: { | 1067 case AsmTyper::kMathPow: { |
| 1068 VisitCallArgs(call); | |
| 981 DCHECK_EQ(kAstF64, call_type); | 1069 DCHECK_EQ(kAstF64, call_type); |
| 982 current_function_builder_->Emit(kExprF64Pow); | 1070 current_function_builder_->Emit(kExprF64Pow); |
| 983 break; | 1071 break; |
| 984 } | 1072 } |
| 985 case AsmTyper::kMathImul: { | 1073 case AsmTyper::kMathImul: { |
| 1074 VisitCallArgs(call); | |
| 986 current_function_builder_->Emit(kExprI32Mul); | 1075 current_function_builder_->Emit(kExprI32Mul); |
| 987 break; | 1076 break; |
| 988 } | 1077 } |
| 989 case AsmTyper::kMathFround: { | 1078 case AsmTyper::kMathFround: { |
| 990 DCHECK(args->length() == 1); | 1079 DCHECK(args->length() == 1); |
| 991 Literal* literal = args->at(0)->AsLiteral(); | 1080 Literal* literal = args->at(0)->AsLiteral(); |
| 992 if (literal != nullptr) { | 1081 if (literal != nullptr) { |
| 1082 // constant fold Math.fround(#const); | |
| 993 if (literal->raw_value()->IsNumber()) { | 1083 if (literal->raw_value()->IsNumber()) { |
| 994 float val = static_cast<float>(literal->raw_value()->AsNumber()); | 1084 float val = static_cast<float>(literal->raw_value()->AsNumber()); |
| 995 byte code[] = {WASM_F32(val)}; | 1085 byte code[] = {WASM_F32(val)}; |
| 996 current_function_builder_->EmitCode(code, sizeof(code)); | 1086 current_function_builder_->EmitCode(code, sizeof(code)); |
| 997 return true; | 1087 return true; |
| 998 } | 1088 } |
| 999 } | 1089 } |
| 1090 VisitCallArgs(call); | |
| 1000 switch (TypeIndexOf(args->at(0))) { | 1091 switch (TypeIndexOf(args->at(0))) { |
| 1001 case kInt32: | 1092 case kInt32: |
| 1002 case kFixnum: | 1093 case kFixnum: |
| 1003 current_function_builder_->Emit(kExprF32SConvertI32); | 1094 current_function_builder_->Emit(kExprF32SConvertI32); |
| 1004 break; | 1095 break; |
| 1005 case kUint32: | 1096 case kUint32: |
| 1006 current_function_builder_->Emit(kExprF32UConvertI32); | 1097 current_function_builder_->Emit(kExprF32UConvertI32); |
| 1007 break; | 1098 break; |
| 1008 case kFloat32: | 1099 case kFloat32: |
| 1009 break; | 1100 break; |
| 1010 case kFloat64: | 1101 case kFloat64: |
| 1011 current_function_builder_->Emit(kExprF32ConvertF64); | 1102 current_function_builder_->Emit(kExprF32ConvertF64); |
| 1012 break; | 1103 break; |
| 1013 default: | 1104 default: |
| 1014 UNREACHABLE(); | 1105 UNREACHABLE(); |
| 1015 } | 1106 } |
| 1016 break; | 1107 break; |
| 1017 } | 1108 } |
| 1018 default: { | 1109 default: { |
| 1019 UNREACHABLE(); | 1110 UNREACHABLE(); |
| 1020 break; | 1111 break; |
| 1021 } | 1112 } |
| 1022 } | 1113 } |
| 1023 VisitCallArgs(call); | |
| 1024 return true; | 1114 return true; |
| 1025 } | 1115 } |
| 1026 | 1116 |
| 1027 void VisitCallArgs(Call* expr) { | 1117 void VisitCallArgs(Call* expr) { |
| 1028 ZoneList<Expression*>* args = expr->arguments(); | 1118 ZoneList<Expression*>* args = expr->arguments(); |
| 1029 for (int i = 0; i < args->length(); ++i) { | 1119 for (int i = 0; i < args->length(); ++i) { |
| 1030 Expression* arg = args->at(i); | 1120 Expression* arg = args->at(i); |
| 1031 RECURSE(Visit(arg)); | 1121 RECURSE(Visit(arg)); |
| 1032 } | 1122 } |
| 1033 } | 1123 } |
| 1034 | 1124 |
| 1035 void VisitCall(Call* expr) { | 1125 void VisitCall(Call* expr) { |
| 1036 Call::CallType call_type = expr->GetCallType(isolate_); | 1126 Call::CallType call_type = expr->GetCallType(isolate_); |
| 1127 std::vector<byte> call_code; | |
| 1037 switch (call_type) { | 1128 switch (call_type) { |
| 1038 case Call::OTHER_CALL: { | 1129 case Call::OTHER_CALL: { |
| 1039 DCHECK(in_function_); | 1130 DCHECK_EQ(kFuncScope, scope_); |
| 1040 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1131 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 1041 if (proxy != nullptr) { | 1132 if (proxy != nullptr) { |
| 1042 if (VisitStdlibFunction(expr, proxy)) { | 1133 if (VisitStdlibFunction(expr, proxy)) { |
| 1043 return; | 1134 return; |
| 1044 } | 1135 } |
| 1045 } | 1136 } |
| 1046 uint16_t index; | 1137 uint16_t index; |
| 1047 VariableProxy* vp = expr->expression()->AsVariableProxy(); | 1138 VariableProxy* vp = expr->expression()->AsVariableProxy(); |
| 1048 if (vp != nullptr && | 1139 if (vp != nullptr && |
| 1049 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { | 1140 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { |
| 1050 LocalType return_type = TypeOf(expr); | 1141 LocalType return_type = TypeOf(expr); |
| 1051 ZoneList<Expression*>* args = expr->arguments(); | 1142 ZoneList<Expression*>* args = expr->arguments(); |
| 1052 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1143 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 1053 args->length()); | 1144 args->length()); |
| 1054 if (return_type != kAstStmt) { | 1145 if (return_type != kAstStmt) { |
| 1055 sig.AddReturn(return_type); | 1146 sig.AddReturn(return_type); |
| 1056 } | 1147 } |
| 1057 for (int i = 0; i < args->length(); i++) { | 1148 for (int i = 0; i < args->length(); i++) { |
| 1058 sig.AddParam(TypeOf(args->at(i))); | 1149 sig.AddParam(TypeOf(args->at(i))); |
| 1059 } | 1150 } |
| 1060 index = | 1151 index = |
| 1061 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); | 1152 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); |
| 1062 } else { | 1153 } else { |
| 1063 index = LookupOrInsertFunction(vp->var()); | 1154 index = LookupOrInsertFunction(vp->var()); |
| 1064 } | 1155 } |
| 1065 current_function_builder_->Emit(kExprCallFunction); | 1156 call_code.push_back(kExprCallFunction); |
| 1066 std::vector<uint8_t> index_arr = UnsignedLEB128From(index); | 1157 // TODO(titzer): inefficient and clunky |
| 1067 current_function_builder_->EmitCode( | 1158 std::vector<byte> leb = UnsignedLEB128From(index); |
| 1068 &index_arr[0], static_cast<uint32_t>(index_arr.size())); | 1159 call_code.insert(call_code.end(), leb.begin(), leb.end()); |
| 1069 break; | 1160 break; |
| 1070 } | 1161 } |
| 1071 case Call::KEYED_PROPERTY_CALL: { | 1162 case Call::KEYED_PROPERTY_CALL: { |
| 1072 DCHECK(in_function_); | 1163 DCHECK_EQ(kFuncScope, scope_); |
| 1073 Property* p = expr->expression()->AsProperty(); | 1164 Property* p = expr->expression()->AsProperty(); |
| 1074 DCHECK_NOT_NULL(p); | 1165 DCHECK_NOT_NULL(p); |
| 1075 VariableProxy* var = p->obj()->AsVariableProxy(); | 1166 VariableProxy* var = p->obj()->AsVariableProxy(); |
| 1076 DCHECK_NOT_NULL(var); | 1167 DCHECK_NOT_NULL(var); |
| 1077 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 1168 FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
| 1078 current_function_builder_->EmitWithVarInt(kExprCallIndirect, | 1169 RECURSE(Visit(p->key())); |
| 1079 indices->signature_index); | 1170 current_function_builder_->EmitI32Const(indices->start_index); |
| 1080 current_function_builder_->Emit(kExprI32Add); | 1171 current_function_builder_->Emit(kExprI32Add); |
| 1081 // TODO(bradnelson): variable size | 1172 call_code.push_back(kExprCallIndirect); |
| 1082 byte code[] = {WASM_I32V(indices->start_index)}; | 1173 // TODO(titzer): inefficient and clunky |
| 1083 current_function_builder_->EmitCode(code, sizeof(code)); | 1174 std::vector<byte> leb = UnsignedLEB128From(indices->signature_index); |
| 1084 RECURSE(Visit(p->key())); | 1175 call_code.insert(call_code.end(), leb.begin(), leb.end()); |
| 1085 break; | 1176 break; |
| 1086 } | 1177 } |
| 1087 default: | 1178 default: |
| 1088 UNREACHABLE(); | 1179 UNREACHABLE(); |
| 1089 } | 1180 } |
| 1090 VisitCallArgs(expr); | 1181 VisitCallArgs(expr); |
| 1182 | |
| 1183 current_function_builder_->EmitCode( | |
| 1184 &call_code[0], static_cast<uint32_t>(call_code.size())); | |
| 1091 } | 1185 } |
| 1092 | 1186 |
| 1093 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } | 1187 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } |
| 1094 | 1188 |
| 1095 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } | 1189 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } |
| 1096 | 1190 |
| 1097 void VisitUnaryOperation(UnaryOperation* expr) { | 1191 void VisitUnaryOperation(UnaryOperation* expr) { |
| 1192 RECURSE(Visit(expr->expression())); | |
| 1098 switch (expr->op()) { | 1193 switch (expr->op()) { |
| 1099 case Token::NOT: { | 1194 case Token::NOT: { |
| 1100 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); | 1195 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); |
| 1101 current_function_builder_->Emit(kExprI32Eqz); | 1196 current_function_builder_->Emit(kExprI32Eqz); |
| 1102 break; | 1197 break; |
| 1103 } | 1198 } |
| 1104 default: | 1199 default: |
| 1105 UNREACHABLE(); | 1200 UNREACHABLE(); |
| 1106 } | 1201 } |
| 1107 RECURSE(Visit(expr->expression())); | |
| 1108 } | 1202 } |
| 1109 | 1203 |
| 1110 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } | 1204 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } |
| 1111 | 1205 |
| 1112 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, | 1206 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, |
| 1113 int32_t val) { | 1207 int32_t val) { |
| 1114 DCHECK_NOT_NULL(expr->right()); | 1208 DCHECK_NOT_NULL(expr->right()); |
| 1115 if (expr->op() == op && expr->right()->IsLiteral() && | 1209 if (expr->op() == op && expr->right()->IsLiteral() && |
| 1116 TypeOf(expr) == kAstI32) { | 1210 TypeOf(expr) == kAstI32) { |
| 1117 Literal* right = expr->right()->AsLiteral(); | 1211 Literal* right = expr->right()->AsLiteral(); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1243 if (expr->op() == Token::BIT_XOR) { | 1337 if (expr->op() == Token::BIT_XOR) { |
| 1244 return expr->left()->AsBinaryOperation()->left(); | 1338 return expr->left()->AsBinaryOperation()->left(); |
| 1245 } else { | 1339 } else { |
| 1246 return expr->left(); | 1340 return expr->left(); |
| 1247 } | 1341 } |
| 1248 } | 1342 } |
| 1249 | 1343 |
| 1250 void VisitBinaryOperation(BinaryOperation* expr) { | 1344 void VisitBinaryOperation(BinaryOperation* expr) { |
| 1251 ConvertOperation convertOperation = MatchBinaryOperation(expr); | 1345 ConvertOperation convertOperation = MatchBinaryOperation(expr); |
| 1252 if (convertOperation == kToDouble) { | 1346 if (convertOperation == kToDouble) { |
| 1347 RECURSE(Visit(expr->left())); | |
| 1253 TypeIndex type = TypeIndexOf(expr->left()); | 1348 TypeIndex type = TypeIndexOf(expr->left()); |
| 1254 if (type == kInt32 || type == kFixnum) { | 1349 if (type == kInt32 || type == kFixnum) { |
| 1255 current_function_builder_->Emit(kExprF64SConvertI32); | 1350 current_function_builder_->Emit(kExprF64SConvertI32); |
| 1256 } else if (type == kUint32) { | 1351 } else if (type == kUint32) { |
| 1257 current_function_builder_->Emit(kExprF64UConvertI32); | 1352 current_function_builder_->Emit(kExprF64UConvertI32); |
| 1258 } else if (type == kFloat32) { | 1353 } else if (type == kFloat32) { |
| 1259 current_function_builder_->Emit(kExprF64ConvertF32); | 1354 current_function_builder_->Emit(kExprF64ConvertF32); |
| 1260 } else { | 1355 } else { |
| 1261 UNREACHABLE(); | 1356 UNREACHABLE(); |
| 1262 } | 1357 } |
| 1263 RECURSE(Visit(expr->left())); | |
| 1264 } else if (convertOperation == kToInt) { | 1358 } else if (convertOperation == kToInt) { |
| 1359 RECURSE(Visit(GetLeft(expr))); | |
| 1265 TypeIndex type = TypeIndexOf(GetLeft(expr)); | 1360 TypeIndex type = TypeIndexOf(GetLeft(expr)); |
| 1266 if (type == kFloat32) { | 1361 if (type == kFloat32) { |
| 1267 current_function_builder_->Emit(kExprI32SConvertF32); | 1362 current_function_builder_->Emit(kExprI32SConvertF32); |
| 1268 } else if (type == kFloat64) { | 1363 } else if (type == kFloat64) { |
| 1269 current_function_builder_->Emit(kExprI32SConvertF64); | 1364 current_function_builder_->Emit(kExprI32SConvertF64); |
| 1270 } else { | 1365 } else { |
| 1271 UNREACHABLE(); | 1366 UNREACHABLE(); |
| 1272 } | 1367 } |
| 1273 RECURSE(Visit(GetLeft(expr))); | |
| 1274 } else if (convertOperation == kAsIs) { | 1368 } else if (convertOperation == kAsIs) { |
| 1275 RECURSE(Visit(GetLeft(expr))); | 1369 RECURSE(Visit(GetLeft(expr))); |
| 1276 } else { | 1370 } else { |
| 1371 if (expr->op() == Token::COMMA) { | |
| 1372 current_function_builder_->Emit(kExprBlock); | |
| 1373 } | |
| 1374 | |
| 1375 RECURSE(Visit(expr->left())); | |
| 1376 RECURSE(Visit(expr->right())); | |
| 1377 | |
| 1378 if (expr->op() == Token::COMMA) { | |
| 1379 current_function_builder_->Emit(kExprEnd); | |
|
bradnelson
2016/03/23 19:14:25
return here vs the break down below, might be more
| |
| 1380 } | |
| 1381 | |
| 1277 switch (expr->op()) { | 1382 switch (expr->op()) { |
| 1278 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); | 1383 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); |
| 1279 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); | 1384 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); |
| 1280 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); | 1385 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); |
| 1281 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); | 1386 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); |
| 1282 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); | 1387 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); |
| 1283 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); | 1388 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); |
| 1284 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); | 1389 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); |
| 1285 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); | 1390 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); |
| 1286 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); | 1391 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); |
| 1287 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); | 1392 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); |
| 1288 case Token::MOD: { | 1393 case Token::MOD: { |
| 1289 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); | 1394 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); |
| 1290 if (type == kInt32) { | 1395 if (type == kInt32) { |
| 1291 current_function_builder_->Emit(kExprI32RemS); | 1396 current_function_builder_->Emit(kExprI32RemS); |
| 1292 } else if (type == kUint32) { | 1397 } else if (type == kUint32) { |
| 1293 current_function_builder_->Emit(kExprI32RemU); | 1398 current_function_builder_->Emit(kExprI32RemU); |
| 1294 } else if (type == kFloat64) { | 1399 } else if (type == kFloat64) { |
| 1295 current_function_builder_->Emit(kExprF64Mod); | 1400 current_function_builder_->Emit(kExprF64Mod); |
| 1296 return; | 1401 return; |
| 1297 } else { | 1402 } else { |
| 1298 UNREACHABLE(); | 1403 UNREACHABLE(); |
| 1299 } | 1404 } |
| 1300 break; | 1405 break; |
| 1301 } | 1406 } |
| 1302 case Token::COMMA: { | 1407 case Token::COMMA: { |
| 1303 current_function_builder_->EmitWithVarInt(kExprBlock, 2); | |
| 1304 break; | 1408 break; |
| 1305 } | 1409 } |
| 1306 default: | 1410 default: |
| 1307 UNREACHABLE(); | 1411 UNREACHABLE(); |
| 1308 } | 1412 } |
| 1309 RECURSE(Visit(expr->left())); | |
| 1310 RECURSE(Visit(expr->right())); | |
| 1311 } | 1413 } |
| 1312 } | 1414 } |
| 1313 | 1415 |
| 1314 void AddLeb128(uint32_t index, bool is_local) { | 1416 void AddLeb128(uint32_t index, bool is_local) { |
| 1315 std::vector<uint8_t> index_vec = UnsignedLEB128From(index); | 1417 std::vector<uint8_t> index_vec = UnsignedLEB128From(index); |
| 1316 if (is_local) { | 1418 if (is_local) { |
| 1317 uint32_t pos_of_index[1] = {0}; | 1419 uint32_t pos_of_index[1] = {0}; |
| 1318 current_function_builder_->EmitCode( | 1420 current_function_builder_->EmitCode( |
| 1319 &index_vec[0], static_cast<uint32_t>(index_vec.size()), pos_of_index, | 1421 &index_vec[0], static_cast<uint32_t>(index_vec.size()), pos_of_index, |
| 1320 1); | 1422 1); |
| 1321 } else { | 1423 } else { |
| 1322 current_function_builder_->EmitCode( | 1424 current_function_builder_->EmitCode( |
| 1323 &index_vec[0], static_cast<uint32_t>(index_vec.size())); | 1425 &index_vec[0], static_cast<uint32_t>(index_vec.size())); |
| 1324 } | 1426 } |
| 1325 } | 1427 } |
| 1326 | 1428 |
| 1327 void VisitCompareOperation(CompareOperation* expr) { | 1429 void VisitCompareOperation(CompareOperation* expr) { |
| 1430 RECURSE(Visit(expr->left())); | |
| 1431 RECURSE(Visit(expr->right())); | |
| 1328 switch (expr->op()) { | 1432 switch (expr->op()) { |
| 1329 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); | 1433 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); |
| 1330 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); | 1434 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); |
| 1331 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); | 1435 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); |
| 1332 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); | 1436 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); |
| 1333 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); | 1437 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); |
| 1334 default: | 1438 default: |
| 1335 UNREACHABLE(); | 1439 UNREACHABLE(); |
| 1336 } | 1440 } |
| 1337 RECURSE(Visit(expr->left())); | |
| 1338 RECURSE(Visit(expr->right())); | |
| 1339 } | 1441 } |
| 1340 | 1442 |
| 1341 #undef BINOP_CASE | 1443 #undef BINOP_CASE |
| 1342 #undef NON_SIGNED_INT_BINOP | 1444 #undef NON_SIGNED_INT_BINOP |
| 1343 #undef SIGNED_BINOP | 1445 #undef SIGNED_BINOP |
| 1344 #undef NON_SIGNED_BINOP | 1446 #undef NON_SIGNED_BINOP |
| 1345 | 1447 |
| 1346 enum TypeIndex { | 1448 enum TypeIndex { |
| 1347 kInt32 = 0, | 1449 kInt32 = 0, |
| 1348 kUint32 = 1, | 1450 kUint32 = 1, |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1490 } else { | 1592 } else { |
| 1491 return kAstStmt; | 1593 return kAstStmt; |
| 1492 } | 1594 } |
| 1493 } | 1595 } |
| 1494 | 1596 |
| 1495 Zone* zone() { return zone_; } | 1597 Zone* zone() { return zone_; } |
| 1496 | 1598 |
| 1497 ZoneHashMap local_variables_; | 1599 ZoneHashMap local_variables_; |
| 1498 ZoneHashMap functions_; | 1600 ZoneHashMap functions_; |
| 1499 ZoneHashMap global_variables_; | 1601 ZoneHashMap global_variables_; |
| 1500 bool in_function_; | 1602 AsmScope scope_; |
| 1501 bool is_set_op_; | |
| 1502 bool marking_exported; | |
| 1503 WasmModuleBuilder* builder_; | 1603 WasmModuleBuilder* builder_; |
| 1504 WasmFunctionBuilder* current_function_builder_; | 1604 WasmFunctionBuilder* current_function_builder_; |
| 1505 FunctionLiteral* literal_; | 1605 FunctionLiteral* literal_; |
| 1506 Isolate* isolate_; | 1606 Isolate* isolate_; |
| 1507 Zone* zone_; | 1607 Zone* zone_; |
| 1508 Handle<Object> foreign_; | 1608 Handle<Object> foreign_; |
| 1509 AsmTyper* typer_; | 1609 AsmTyper* typer_; |
| 1510 TypeCache const& cache_; | 1610 TypeCache const& cache_; |
| 1511 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1611 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
| 1512 int block_size_; | |
| 1513 uint16_t init_function_index_; | 1612 uint16_t init_function_index_; |
| 1514 uint32_t next_table_index_; | 1613 uint32_t next_table_index_; |
| 1515 ZoneHashMap function_tables_; | 1614 ZoneHashMap function_tables_; |
| 1516 ImportedFunctionTable imported_function_table_; | 1615 ImportedFunctionTable imported_function_table_; |
| 1517 | 1616 |
| 1518 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1617 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 1519 | 1618 |
| 1520 private: | 1619 private: |
| 1521 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1620 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
| 1522 }; | 1621 }; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1534 // that zone in constructor may be thrown away once wasm module is written. | 1633 // that zone in constructor may be thrown away once wasm module is written. |
| 1535 WasmModuleIndex* AsmWasmBuilder::Run() { | 1634 WasmModuleIndex* AsmWasmBuilder::Run() { |
| 1536 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); | 1635 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); |
| 1537 impl.Compile(); | 1636 impl.Compile(); |
| 1538 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1637 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
| 1539 return writer->WriteTo(zone_); | 1638 return writer->WriteTo(zone_); |
| 1540 } | 1639 } |
| 1541 } // namespace wasm | 1640 } // namespace wasm |
| 1542 } // namespace internal | 1641 } // namespace internal |
| 1543 } // namespace v8 | 1642 } // namespace v8 |
| OLD | NEW |