| 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 13 matching lines...) Expand all Loading... |
| 24 namespace internal { | 24 namespace internal { |
| 25 namespace wasm { | 25 namespace wasm { |
| 26 | 26 |
| 27 #define RECURSE(call) \ | 27 #define RECURSE(call) \ |
| 28 do { \ | 28 do { \ |
| 29 DCHECK(!HasStackOverflow()); \ | 29 DCHECK(!HasStackOverflow()); \ |
| 30 call; \ | 30 call; \ |
| 31 if (HasStackOverflow()) return; \ | 31 if (HasStackOverflow()) return; \ |
| 32 } while (false) | 32 } while (false) |
| 33 | 33 |
| 34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; |
| 34 | 35 |
| 35 class AsmWasmBuilderImpl : public AstVisitor { | 36 class AsmWasmBuilderImpl : public AstVisitor { |
| 36 public: | 37 public: |
| 37 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 38 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
| 38 Handle<Object> foreign, AsmTyper* typer) | 39 Handle<Object> foreign, AsmTyper* typer) |
| 39 : local_variables_(HashMap::PointersMatch, | 40 : local_variables_(HashMap::PointersMatch, |
| 40 ZoneHashMap::kDefaultHashMapCapacity, | 41 ZoneHashMap::kDefaultHashMapCapacity, |
| 41 ZoneAllocationPolicy(zone)), | 42 ZoneAllocationPolicy(zone)), |
| 42 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | 43 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, |
| 43 ZoneAllocationPolicy(zone)), | 44 ZoneAllocationPolicy(zone)), |
| 44 global_variables_(HashMap::PointersMatch, | 45 global_variables_(HashMap::PointersMatch, |
| 45 ZoneHashMap::kDefaultHashMapCapacity, | 46 ZoneHashMap::kDefaultHashMapCapacity, |
| 46 ZoneAllocationPolicy(zone)), | 47 ZoneAllocationPolicy(zone)), |
| 47 in_function_(false), | 48 scope_(kModuleScope), |
| 48 is_set_op_(false), | |
| 49 marking_exported(false), | |
| 50 builder_(new (zone) WasmModuleBuilder(zone)), | 49 builder_(new (zone) WasmModuleBuilder(zone)), |
| 51 current_function_builder_(nullptr), | 50 current_function_builder_(nullptr), |
| 52 literal_(literal), | 51 literal_(literal), |
| 53 isolate_(isolate), | 52 isolate_(isolate), |
| 54 zone_(zone), | 53 zone_(zone), |
| 55 foreign_(foreign), | 54 foreign_(foreign), |
| 56 typer_(typer), | 55 typer_(typer), |
| 57 cache_(TypeCache::Get()), | 56 cache_(TypeCache::Get()), |
| 58 breakable_blocks_(zone), | 57 breakable_blocks_(zone), |
| 59 block_size_(0), | |
| 60 init_function_index_(0), | 58 init_function_index_(0), |
| 61 next_table_index_(0), | 59 next_table_index_(0), |
| 62 function_tables_(HashMap::PointersMatch, | 60 function_tables_(HashMap::PointersMatch, |
| 63 ZoneHashMap::kDefaultHashMapCapacity, | 61 ZoneHashMap::kDefaultHashMapCapacity, |
| 64 ZoneAllocationPolicy(zone)), | 62 ZoneAllocationPolicy(zone)), |
| 65 imported_function_table_(this) { | 63 imported_function_table_(this) { |
| 66 InitializeAstVisitor(isolate); | 64 InitializeAstVisitor(isolate); |
| 67 } | 65 } |
| 68 | 66 |
| 69 void InitializeInitFunction() { | 67 void InitializeInitFunction() { |
| 70 init_function_index_ = builder_->AddFunction(); | 68 init_function_index_ = builder_->AddFunction(); |
| 71 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 69 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 72 current_function_builder_->ReturnType(kAstStmt); | 70 current_function_builder_->ReturnType(kAstStmt); |
| 73 builder_->MarkStartFunction(init_function_index_); | 71 builder_->MarkStartFunction(init_function_index_); |
| 74 current_function_builder_ = nullptr; | 72 current_function_builder_ = nullptr; |
| 75 } | 73 } |
| 76 | 74 |
| 77 void Compile() { | 75 void Compile() { |
| 78 InitializeInitFunction(); | 76 InitializeInitFunction(); |
| 79 RECURSE(VisitFunctionLiteral(literal_)); | 77 RECURSE(VisitFunctionLiteral(literal_)); |
| 80 } | 78 } |
| 81 | 79 |
| 82 void VisitVariableDeclaration(VariableDeclaration* decl) {} | 80 void VisitVariableDeclaration(VariableDeclaration* decl) {} |
| 83 | 81 |
| 84 void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 82 void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 85 DCHECK(!in_function_); | 83 DCHECK_EQ(kModuleScope, scope_); |
| 86 DCHECK_NULL(current_function_builder_); | 84 DCHECK_NULL(current_function_builder_); |
| 87 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); | 85 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); |
| 88 current_function_builder_ = builder_->FunctionAt(index); | 86 current_function_builder_ = builder_->FunctionAt(index); |
| 89 in_function_ = true; | 87 scope_ = kFuncScope; |
| 90 RECURSE(Visit(decl->fun())); | 88 RECURSE(Visit(decl->fun())); |
| 91 in_function_ = false; | 89 scope_ = kModuleScope; |
| 92 current_function_builder_ = nullptr; | 90 current_function_builder_ = nullptr; |
| 93 local_variables_.Clear(); | 91 local_variables_.Clear(); |
| 94 } | 92 } |
| 95 | 93 |
| 96 void VisitImportDeclaration(ImportDeclaration* decl) {} | 94 void VisitImportDeclaration(ImportDeclaration* decl) {} |
| 97 | 95 |
| 98 void VisitExportDeclaration(ExportDeclaration* decl) {} | 96 void VisitExportDeclaration(ExportDeclaration* decl) {} |
| 99 | 97 |
| 100 void VisitStatements(ZoneList<Statement*>* stmts) { | 98 void VisitStatements(ZoneList<Statement*>* stmts) { |
| 101 for (int i = 0; i < stmts->length(); ++i) { | 99 for (int i = 0; i < stmts->length(); ++i) { |
| 102 Statement* stmt = stmts->at(i); | 100 Statement* stmt = stmts->at(i); |
| 103 ExpressionStatement* e = stmt->AsExpressionStatement(); | 101 ExpressionStatement* e = stmt->AsExpressionStatement(); |
| 104 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { | 102 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { |
| 105 block_size_--; | |
| 106 continue; | 103 continue; |
| 107 } | 104 } |
| 108 RECURSE(Visit(stmt)); | 105 RECURSE(Visit(stmt)); |
| 109 if (stmt->IsJump()) break; | 106 if (stmt->IsJump()) break; |
| 110 } | 107 } |
| 111 } | 108 } |
| 112 | 109 |
| 113 void VisitBlock(Block* stmt) { | 110 void VisitBlock(Block* stmt) { |
| 114 if (stmt->statements()->length() == 1) { | 111 if (stmt->statements()->length() == 1) { |
| 115 ExpressionStatement* expr = | 112 ExpressionStatement* expr = |
| 116 stmt->statements()->at(0)->AsExpressionStatement(); | 113 stmt->statements()->at(0)->AsExpressionStatement(); |
| 117 if (expr != nullptr) { | 114 if (expr != nullptr) { |
| 118 if (expr->expression()->IsAssignment()) { | 115 if (expr->expression()->IsAssignment()) { |
| 119 RECURSE(VisitExpressionStatement(expr)); | 116 RECURSE(VisitExpressionStatement(expr)); |
| 120 return; | 117 return; |
| 121 } | 118 } |
| 122 } | 119 } |
| 123 } | 120 } |
| 124 if (in_function_) { | 121 if (scope_ == kFuncScope) { |
| 125 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, | 122 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |
| 126 false, | 123 false); |
| 127 static_cast<byte>(stmt->statements()->length())); | |
| 128 RECURSE(VisitStatements(stmt->statements())); | 124 RECURSE(VisitStatements(stmt->statements())); |
| 129 DCHECK(block_size_ >= 0); | |
| 130 } else { | 125 } else { |
| 131 RECURSE(VisitStatements(stmt->statements())); | 126 RECURSE(VisitStatements(stmt->statements())); |
| 132 } | 127 } |
| 133 } | 128 } |
| 134 | 129 |
| 135 class BlockVisitor { | 130 class BlockVisitor { |
| 136 private: | 131 private: |
| 137 int prev_block_size_; | |
| 138 uint32_t index_; | |
| 139 AsmWasmBuilderImpl* builder_; | 132 AsmWasmBuilderImpl* builder_; |
| 140 | 133 |
| 141 public: | 134 public: |
| 142 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, | 135 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, |
| 143 WasmOpcode opcode, bool is_loop, int initial_block_size) | 136 WasmOpcode opcode, bool is_loop) |
| 144 : builder_(builder) { | 137 : builder_(builder) { |
| 145 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); | 138 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); |
| 146 builder_->current_function_builder_->Emit(opcode); | 139 builder_->current_function_builder_->Emit(opcode); |
| 147 index_ = | |
| 148 builder_->current_function_builder_->EmitEditableVarIntImmediate(); | |
| 149 prev_block_size_ = builder_->block_size_; | |
| 150 builder_->block_size_ = initial_block_size; | |
| 151 } | 140 } |
| 152 ~BlockVisitor() { | 141 ~BlockVisitor() { |
| 153 builder_->current_function_builder_->EditVarIntImmediate( | 142 builder_->current_function_builder_->Emit(kExprEnd); |
| 154 index_, builder_->block_size_); | |
| 155 builder_->block_size_ = prev_block_size_; | |
| 156 builder_->breakable_blocks_.pop_back(); | 143 builder_->breakable_blocks_.pop_back(); |
| 157 } | 144 } |
| 158 }; | 145 }; |
| 159 | 146 |
| 160 void VisitExpressionStatement(ExpressionStatement* stmt) { | 147 void VisitExpressionStatement(ExpressionStatement* stmt) { |
| 161 RECURSE(Visit(stmt->expression())); | 148 RECURSE(Visit(stmt->expression())); |
| 162 } | 149 } |
| 163 | 150 |
| 164 void VisitEmptyStatement(EmptyStatement* stmt) {} | 151 void VisitEmptyStatement(EmptyStatement* stmt) {} |
| 165 | 152 |
| 166 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } | 153 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } |
| 167 | 154 |
| 168 void VisitIfStatement(IfStatement* stmt) { | 155 void VisitIfStatement(IfStatement* stmt) { |
| 169 DCHECK(in_function_); | 156 DCHECK_EQ(kFuncScope, scope_); |
| 170 if (stmt->HasElseStatement()) { | |
| 171 current_function_builder_->Emit(kExprIfElse); | |
| 172 } else { | |
| 173 current_function_builder_->Emit(kExprIf); | |
| 174 } | |
| 175 RECURSE(Visit(stmt->condition())); | 157 RECURSE(Visit(stmt->condition())); |
| 158 current_function_builder_->Emit(kExprIf); |
| 159 // WASM ifs come with implement blocks for both arms. |
| 160 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 176 if (stmt->HasThenStatement()) { | 161 if (stmt->HasThenStatement()) { |
| 177 RECURSE(Visit(stmt->then_statement())); | 162 RECURSE(Visit(stmt->then_statement())); |
| 178 } else { | |
| 179 current_function_builder_->Emit(kExprNop); | |
| 180 } | 163 } |
| 181 if (stmt->HasElseStatement()) { | 164 if (stmt->HasElseStatement()) { |
| 165 current_function_builder_->Emit(kExprElse); |
| 182 RECURSE(Visit(stmt->else_statement())); | 166 RECURSE(Visit(stmt->else_statement())); |
| 183 } | 167 } |
| 168 current_function_builder_->Emit(kExprEnd); |
| 169 breakable_blocks_.pop_back(); |
| 184 } | 170 } |
| 185 | 171 |
| 186 void VisitContinueStatement(ContinueStatement* stmt) { | 172 void VisitContinueStatement(ContinueStatement* stmt) { |
| 187 DCHECK(in_function_); | 173 DCHECK_EQ(kFuncScope, scope_); |
| 188 DCHECK_NOT_NULL(stmt->target()); | 174 DCHECK_NOT_NULL(stmt->target()); |
| 189 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 175 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
| 190 int block_distance = 0; | 176 int block_distance = 0; |
| 191 for (; i >= 0; i--) { | 177 for (; i >= 0; i--) { |
| 192 auto elem = breakable_blocks_.at(i); | 178 auto elem = breakable_blocks_.at(i); |
| 193 if (elem.first == stmt->target()) { | 179 if (elem.first == stmt->target()) { |
| 194 DCHECK(elem.second); | 180 DCHECK(elem.second); |
| 195 break; | 181 break; |
| 196 } else if (elem.second) { | 182 } else if (elem.second) { |
| 197 block_distance += 2; | 183 block_distance += 2; |
| 198 } else { | 184 } else { |
| 199 block_distance += 1; | 185 block_distance += 1; |
| 200 } | 186 } |
| 201 } | 187 } |
| 202 DCHECK(i >= 0); | 188 DCHECK(i >= 0); |
| 203 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | |
| 204 current_function_builder_->Emit(kExprNop); | 189 current_function_builder_->Emit(kExprNop); |
| 190 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
| 191 current_function_builder_->EmitVarInt(block_distance); |
| 205 } | 192 } |
| 206 | 193 |
| 207 void VisitBreakStatement(BreakStatement* stmt) { | 194 void VisitBreakStatement(BreakStatement* stmt) { |
| 208 DCHECK(in_function_); | 195 DCHECK_EQ(kFuncScope, scope_); |
| 209 DCHECK_NOT_NULL(stmt->target()); | 196 DCHECK_NOT_NULL(stmt->target()); |
| 210 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 197 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
| 211 int block_distance = 0; | 198 int block_distance = 0; |
| 212 for (; i >= 0; i--) { | 199 for (; i >= 0; i--) { |
| 213 auto elem = breakable_blocks_.at(i); | 200 auto elem = breakable_blocks_.at(i); |
| 214 if (elem.first == stmt->target()) { | 201 if (elem.first == stmt->target()) { |
| 215 if (elem.second) { | 202 if (elem.second) { |
| 216 block_distance++; | 203 block_distance++; |
| 217 } | 204 } |
| 218 break; | 205 break; |
| 219 } else if (elem.second) { | 206 } else if (elem.second) { |
| 220 block_distance += 2; | 207 block_distance += 2; |
| 221 } else { | 208 } else { |
| 222 block_distance += 1; | 209 block_distance += 1; |
| 223 } | 210 } |
| 224 } | 211 } |
| 225 DCHECK(i >= 0); | 212 DCHECK(i >= 0); |
| 226 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | |
| 227 current_function_builder_->Emit(kExprNop); | 213 current_function_builder_->Emit(kExprNop); |
| 214 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
| 215 current_function_builder_->EmitVarInt(block_distance); |
| 228 } | 216 } |
| 229 | 217 |
| 230 void VisitReturnStatement(ReturnStatement* stmt) { | 218 void VisitReturnStatement(ReturnStatement* stmt) { |
| 231 if (in_function_) { | 219 if (scope_ == kModuleScope) { |
| 232 current_function_builder_->Emit(kExprReturn); | 220 scope_ = kExportScope; |
| 221 RECURSE(Visit(stmt->expression())); |
| 222 scope_ = kModuleScope; |
| 223 } else if (scope_ == kFuncScope) { |
| 224 RECURSE(Visit(stmt->expression())); |
| 225 uint8_t arity = |
| 226 TypeOf(stmt->expression()) == kAstStmt ? ARITY_0 : ARITY_1; |
| 227 current_function_builder_->EmitWithU8(kExprReturn, arity); |
| 233 } else { | 228 } else { |
| 234 marking_exported = true; | 229 UNREACHABLE(); |
| 235 } | |
| 236 RECURSE(Visit(stmt->expression())); | |
| 237 if (!in_function_) { | |
| 238 marking_exported = false; | |
| 239 } | 230 } |
| 240 } | 231 } |
| 241 | 232 |
| 242 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } | 233 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } |
| 243 | 234 |
| 244 void GenerateCaseComparisonCode(int value, WasmOpcode op, | |
| 245 VariableProxy* tag) { | |
| 246 current_function_builder_->Emit(kExprIfElse); | |
| 247 current_function_builder_->Emit(op); | |
| 248 VisitVariableProxy(tag); | |
| 249 byte code[] = {WASM_I32V(value)}; | |
| 250 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 251 } | |
| 252 | |
| 253 void HandleCase(CaseNode* node, | 235 void HandleCase(CaseNode* node, |
| 254 const ZoneMap<int, unsigned int>& case_to_block, | 236 const ZoneMap<int, unsigned int>& case_to_block, |
| 255 VariableProxy* tag, int default_block) { | 237 VariableProxy* tag, int default_block, int if_depth) { |
| 238 int prev_if_depth = if_depth; |
| 256 if (node->left != nullptr) { | 239 if (node->left != nullptr) { |
| 257 GenerateCaseComparisonCode(node->begin, kExprI32LtS, tag); | 240 VisitVariableProxy(tag); |
| 258 HandleCase(node->left, case_to_block, tag, default_block); | 241 current_function_builder_->EmitI32Const(node->begin); |
| 242 current_function_builder_->Emit(kExprI32LtS); |
| 243 current_function_builder_->Emit(kExprIf); |
| 244 if_depth++; |
| 245 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 246 HandleCase(node->left, case_to_block, tag, default_block, if_depth); |
| 247 current_function_builder_->Emit(kExprElse); |
| 259 } | 248 } |
| 260 if (node->right != nullptr) { | 249 if (node->right != nullptr) { |
| 261 GenerateCaseComparisonCode(node->end, kExprI32GtS, tag); | 250 VisitVariableProxy(tag); |
| 262 HandleCase(node->right, case_to_block, tag, default_block); | 251 current_function_builder_->EmitI32Const(node->end); |
| 252 current_function_builder_->Emit(kExprI32GtS); |
| 253 current_function_builder_->Emit(kExprIf); |
| 254 if_depth++; |
| 255 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 256 HandleCase(node->right, case_to_block, tag, default_block, if_depth); |
| 257 current_function_builder_->Emit(kExprElse); |
| 263 } | 258 } |
| 264 if (node->begin == node->end) { | 259 if (node->begin == node->end) { |
| 260 VisitVariableProxy(tag); |
| 261 current_function_builder_->EmitI32Const(node->begin); |
| 262 current_function_builder_->Emit(kExprI32Eq); |
| 265 current_function_builder_->Emit(kExprIf); | 263 current_function_builder_->Emit(kExprIf); |
| 266 current_function_builder_->Emit(kExprI32Eq); | |
| 267 VisitVariableProxy(tag); | |
| 268 byte code[] = {WASM_I32V(node->begin)}; | |
| 269 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 270 DCHECK(case_to_block.find(node->begin) != case_to_block.end()); | 264 DCHECK(case_to_block.find(node->begin) != case_to_block.end()); |
| 271 current_function_builder_->EmitWithVarInt(kExprBr, | |
| 272 case_to_block.at(node->begin)); | |
| 273 current_function_builder_->Emit(kExprNop); | 265 current_function_builder_->Emit(kExprNop); |
| 266 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
| 267 current_function_builder_->EmitVarInt(1 + if_depth + |
| 268 case_to_block.at(node->begin)); |
| 269 current_function_builder_->Emit(kExprEnd); |
| 274 } else { | 270 } else { |
| 275 current_function_builder_->Emit(kExprBrTable); | 271 current_function_builder_->Emit(kExprNop); |
| 272 if (node->begin != 0) { |
| 273 VisitVariableProxy(tag); |
| 274 current_function_builder_->EmitI32Const(node->begin); |
| 275 current_function_builder_->Emit(kExprI32Sub); |
| 276 } else { |
| 277 VisitVariableProxy(tag); |
| 278 } |
| 279 current_function_builder_->EmitWithU8(kExprBrTable, ARITY_0); |
| 276 current_function_builder_->EmitVarInt(node->end - node->begin + 1); | 280 current_function_builder_->EmitVarInt(node->end - node->begin + 1); |
| 277 for (int v = node->begin; v <= node->end; v++) { | 281 for (int v = node->begin; v <= node->end; v++) { |
| 278 if (case_to_block.find(v) != case_to_block.end()) { | 282 if (case_to_block.find(v) != case_to_block.end()) { |
| 279 byte break_code[] = {BR_TARGET(case_to_block.at(v))}; | 283 byte break_code[] = {BR_TARGET(if_depth + case_to_block.at(v))}; |
| 280 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 284 current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
| 281 } else { | 285 } else { |
| 282 byte break_code[] = {BR_TARGET(default_block)}; | 286 byte break_code[] = {BR_TARGET(if_depth + default_block)}; |
| 283 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 287 current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
| 284 } | 288 } |
| 285 if (v == kMaxInt) { | 289 if (v == kMaxInt) { |
| 286 break; | 290 break; |
| 287 } | 291 } |
| 288 } | 292 } |
| 289 byte break_code[] = {BR_TARGET(default_block)}; | 293 byte break_code[] = {BR_TARGET(if_depth + default_block)}; |
| 290 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 294 current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
| 291 // TODO(aseemgarg): remove the if once sub 0 is fixed | 295 } |
| 292 if (node->begin != 0) { | 296 |
| 293 current_function_builder_->Emit(kExprI32Sub); | 297 while (if_depth-- != prev_if_depth) { |
| 294 VisitVariableProxy(tag); | 298 breakable_blocks_.pop_back(); |
| 295 byte code[] = {WASM_I32V(node->begin)}; | 299 current_function_builder_->Emit(kExprEnd); |
| 296 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 297 } else { | |
| 298 VisitVariableProxy(tag); | |
| 299 } | |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 | 302 |
| 303 void VisitSwitchStatement(SwitchStatement* stmt) { | 303 void VisitSwitchStatement(SwitchStatement* stmt) { |
| 304 VariableProxy* tag = stmt->tag()->AsVariableProxy(); | 304 VariableProxy* tag = stmt->tag()->AsVariableProxy(); |
| 305 DCHECK_NOT_NULL(tag); | 305 DCHECK_NOT_NULL(tag); |
| 306 ZoneList<CaseClause*>* clauses = stmt->cases(); | 306 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 307 int case_count = clauses->length(); | 307 int case_count = clauses->length(); |
| 308 if (case_count == 0) { | 308 if (case_count == 0) { |
| 309 block_size_--; | |
| 310 return; | 309 return; |
| 311 } | 310 } |
| 312 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false, | 311 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false); |
| 313 1); | |
| 314 ZoneVector<BlockVisitor*> blocks(zone_); | 312 ZoneVector<BlockVisitor*> blocks(zone_); |
| 315 ZoneVector<int32_t> cases(zone_); | 313 ZoneVector<int32_t> cases(zone_); |
| 316 ZoneMap<int, unsigned int> case_to_block(zone_); | 314 ZoneMap<int, unsigned int> case_to_block(zone_); |
| 317 bool has_default = false; | 315 bool has_default = false; |
| 318 for (int i = case_count - 1; i >= 0; i--) { | 316 for (int i = case_count - 1; i >= 0; i--) { |
| 319 CaseClause* clause = clauses->at(i); | 317 CaseClause* clause = clauses->at(i); |
| 320 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false, | 318 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false)); |
| 321 clause->statements()->length() + 1)); | |
| 322 if (!clause->is_default()) { | 319 if (!clause->is_default()) { |
| 323 Literal* label = clause->label()->AsLiteral(); | 320 Literal* label = clause->label()->AsLiteral(); |
| 324 Handle<Object> value = label->value(); | 321 Handle<Object> value = label->value(); |
| 325 DCHECK(value->IsNumber() && | 322 DCHECK(value->IsNumber() && |
| 326 label->bounds().upper->Is(cache_.kAsmSigned)); | 323 label->bounds().upper->Is(cache_.kAsmSigned)); |
| 327 int32_t label_value; | 324 int32_t label_value; |
| 328 if (!value->ToInt32(&label_value)) { | 325 if (!value->ToInt32(&label_value)) { |
| 329 UNREACHABLE(); | 326 UNREACHABLE(); |
| 330 } | 327 } |
| 331 case_to_block[label_value] = i; | 328 case_to_block[label_value] = i; |
| 332 cases.push_back(label_value); | 329 cases.push_back(label_value); |
| 333 } else { | 330 } else { |
| 334 DCHECK_EQ(i, case_count - 1); | 331 DCHECK_EQ(i, case_count - 1); |
| 335 has_default = true; | 332 has_default = true; |
| 336 } | 333 } |
| 337 } | 334 } |
| 338 if (!has_default || case_count > 1) { | 335 if (!has_default || case_count > 1) { |
| 339 int default_block = has_default ? case_count - 1 : case_count; | 336 int default_block = has_default ? case_count - 1 : case_count; |
| 340 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false, 1); | 337 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false); |
| 341 CaseNode* root = OrderCases(&cases, zone_); | 338 CaseNode* root = OrderCases(&cases, zone_); |
| 342 HandleCase(root, case_to_block, tag, default_block); | 339 HandleCase(root, case_to_block, tag, default_block, 0); |
| 343 if (root->left != nullptr || root->right != nullptr || | 340 if (root->left != nullptr || root->right != nullptr || |
| 344 root->begin == root->end) { | 341 root->begin == root->end) { |
| 345 block_size_++; | 342 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
| 346 current_function_builder_->EmitWithVarInt(kExprBr, default_block); | 343 current_function_builder_->EmitVarInt(default_block); |
| 347 current_function_builder_->Emit(kExprNop); | 344 current_function_builder_->Emit(kExprNop); |
| 348 } | 345 } |
| 349 } else { | |
| 350 block_size_ = clauses->at(0)->statements()->length(); | |
| 351 } | 346 } |
| 352 for (int i = 0; i < case_count; i++) { | 347 for (int i = 0; i < case_count; i++) { |
| 353 CaseClause* clause = clauses->at(i); | 348 CaseClause* clause = clauses->at(i); |
| 354 RECURSE(VisitStatements(clause->statements())); | 349 RECURSE(VisitStatements(clause->statements())); |
| 355 BlockVisitor* v = blocks.at(case_count - i - 1); | 350 BlockVisitor* v = blocks.at(case_count - i - 1); |
| 356 blocks.pop_back(); | 351 blocks.pop_back(); |
| 357 delete v; | 352 delete v; |
| 358 } | 353 } |
| 359 } | 354 } |
| 360 | 355 |
| 361 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 356 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |
| 362 | 357 |
| 363 void VisitDoWhileStatement(DoWhileStatement* stmt) { | 358 void VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 364 DCHECK(in_function_); | 359 DCHECK_EQ(kFuncScope, scope_); |
| 365 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 360 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
| 366 2); | |
| 367 RECURSE(Visit(stmt->body())); | 361 RECURSE(Visit(stmt->body())); |
| 362 RECURSE(Visit(stmt->cond())); |
| 368 current_function_builder_->Emit(kExprIf); | 363 current_function_builder_->Emit(kExprIf); |
| 369 RECURSE(Visit(stmt->cond())); | 364 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |
| 370 current_function_builder_->EmitWithVarInt(kExprBr, 0); | 365 current_function_builder_->Emit(kExprEnd); |
| 371 current_function_builder_->Emit(kExprNop); | |
| 372 } | 366 } |
| 373 | 367 |
| 374 void VisitWhileStatement(WhileStatement* stmt) { | 368 void VisitWhileStatement(WhileStatement* stmt) { |
| 375 DCHECK(in_function_); | 369 DCHECK_EQ(kFuncScope, scope_); |
| 376 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 370 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
| 377 1); | 371 RECURSE(Visit(stmt->cond())); |
| 372 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 378 current_function_builder_->Emit(kExprIf); | 373 current_function_builder_->Emit(kExprIf); |
| 379 RECURSE(Visit(stmt->cond())); | |
| 380 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
| 381 RECURSE(Visit(stmt->body())); | 374 RECURSE(Visit(stmt->body())); |
| 375 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |
| 376 current_function_builder_->Emit(kExprEnd); |
| 377 breakable_blocks_.pop_back(); |
| 382 } | 378 } |
| 383 | 379 |
| 384 void VisitForStatement(ForStatement* stmt) { | 380 void VisitForStatement(ForStatement* stmt) { |
| 385 DCHECK(in_function_); | 381 DCHECK_EQ(kFuncScope, scope_); |
| 386 if (stmt->init() != nullptr) { | 382 if (stmt->init() != nullptr) { |
| 387 block_size_++; | |
| 388 RECURSE(Visit(stmt->init())); | 383 RECURSE(Visit(stmt->init())); |
| 389 } | 384 } |
| 390 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 385 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
| 391 0); | |
| 392 if (stmt->cond() != nullptr) { | 386 if (stmt->cond() != nullptr) { |
| 393 block_size_++; | 387 RECURSE(Visit(stmt->cond())); |
| 388 current_function_builder_->Emit(kExprI32Eqz); |
| 394 current_function_builder_->Emit(kExprIf); | 389 current_function_builder_->Emit(kExprIf); |
| 395 current_function_builder_->Emit(kExprI32Eqz); | |
| 396 RECURSE(Visit(stmt->cond())); | |
| 397 current_function_builder_->EmitWithVarInt(kExprBr, 1); | |
| 398 current_function_builder_->Emit(kExprNop); | 390 current_function_builder_->Emit(kExprNop); |
| 391 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 2); |
| 392 current_function_builder_->Emit(kExprEnd); |
| 399 } | 393 } |
| 400 if (stmt->body() != nullptr) { | 394 if (stmt->body() != nullptr) { |
| 401 block_size_++; | |
| 402 RECURSE(Visit(stmt->body())); | 395 RECURSE(Visit(stmt->body())); |
| 403 } | 396 } |
| 404 if (stmt->next() != nullptr) { | 397 if (stmt->next() != nullptr) { |
| 405 block_size_++; | |
| 406 RECURSE(Visit(stmt->next())); | 398 RECURSE(Visit(stmt->next())); |
| 407 } | 399 } |
| 408 block_size_++; | |
| 409 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
| 410 current_function_builder_->Emit(kExprNop); | 400 current_function_builder_->Emit(kExprNop); |
| 401 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 0); |
| 411 } | 402 } |
| 412 | 403 |
| 413 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } | 404 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } |
| 414 | 405 |
| 415 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } | 406 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } |
| 416 | 407 |
| 417 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } | 408 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } |
| 418 | 409 |
| 419 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } | 410 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } |
| 420 | 411 |
| 421 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } | 412 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } |
| 422 | 413 |
| 423 void VisitFunctionLiteral(FunctionLiteral* expr) { | 414 void VisitFunctionLiteral(FunctionLiteral* expr) { |
| 424 Scope* scope = expr->scope(); | 415 Scope* scope = expr->scope(); |
| 425 if (in_function_) { | 416 if (scope_ == kFuncScope) { |
| 426 if (expr->bounds().lower->IsFunction()) { | 417 if (expr->bounds().lower->IsFunction()) { |
| 427 FunctionType* func_type = expr->bounds().lower->AsFunction(); | 418 FunctionType* func_type = expr->bounds().lower->AsFunction(); |
| 428 LocalType return_type = TypeFrom(func_type->Result()); | 419 LocalType return_type = TypeFrom(func_type->Result()); |
| 429 current_function_builder_->ReturnType(return_type); | 420 current_function_builder_->ReturnType(return_type); |
| 430 for (int i = 0; i < expr->parameter_count(); i++) { | 421 for (int i = 0; i < expr->parameter_count(); i++) { |
| 431 LocalType type = TypeFrom(func_type->Parameter(i)); | 422 LocalType type = TypeFrom(func_type->Parameter(i)); |
| 432 DCHECK_NE(kAstStmt, type); | 423 DCHECK_NE(kAstStmt, type); |
| 433 LookupOrInsertLocal(scope->parameter(i), type); | 424 LookupOrInsertLocal(scope->parameter(i), type); |
| 434 } | 425 } |
| 435 } else { | 426 } else { |
| 436 UNREACHABLE(); | 427 UNREACHABLE(); |
| 437 } | 428 } |
| 438 } | 429 } |
| 439 RECURSE(VisitStatements(expr->body())); | 430 RECURSE(VisitStatements(expr->body())); |
| 440 RECURSE(VisitDeclarations(scope->declarations())); | 431 RECURSE(VisitDeclarations(scope->declarations())); |
| 441 } | 432 } |
| 442 | 433 |
| 443 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 434 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 444 UNREACHABLE(); | 435 UNREACHABLE(); |
| 445 } | 436 } |
| 446 | 437 |
| 447 void VisitConditional(Conditional* expr) { | 438 void VisitConditional(Conditional* expr) { |
| 448 DCHECK(in_function_); | 439 DCHECK_EQ(kFuncScope, scope_); |
| 449 current_function_builder_->Emit(kExprIfElse); | |
| 450 RECURSE(Visit(expr->condition())); | 440 RECURSE(Visit(expr->condition())); |
| 441 // WASM ifs come with implicit blocks for both arms. |
| 442 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 443 current_function_builder_->Emit(kExprIf); |
| 451 RECURSE(Visit(expr->then_expression())); | 444 RECURSE(Visit(expr->then_expression())); |
| 445 current_function_builder_->Emit(kExprElse); |
| 452 RECURSE(Visit(expr->else_expression())); | 446 RECURSE(Visit(expr->else_expression())); |
| 447 current_function_builder_->Emit(kExprEnd); |
| 448 breakable_blocks_.pop_back(); |
| 453 } | 449 } |
| 454 | 450 |
| 455 bool VisitStdlibConstant(Variable* var) { | 451 bool VisitStdlibConstant(Variable* var) { |
| 456 AsmTyper::StandardMember standard_object = | 452 AsmTyper::StandardMember standard_object = |
| 457 typer_->VariableAsStandardMember(var); | 453 typer_->VariableAsStandardMember(var); |
| 458 double value; | 454 double value; |
| 459 switch (standard_object) { | 455 switch (standard_object) { |
| 460 case AsmTyper::kInfinity: { | 456 case AsmTyper::kInfinity: { |
| 461 value = std::numeric_limits<double>::infinity(); | 457 value = std::numeric_limits<double>::infinity(); |
| 462 break; | 458 break; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 break; | 494 break; |
| 499 } | 495 } |
| 500 default: { return false; } | 496 default: { return false; } |
| 501 } | 497 } |
| 502 byte code[] = {WASM_F64(value)}; | 498 byte code[] = {WASM_F64(value)}; |
| 503 current_function_builder_->EmitCode(code, sizeof(code)); | 499 current_function_builder_->EmitCode(code, sizeof(code)); |
| 504 return true; | 500 return true; |
| 505 } | 501 } |
| 506 | 502 |
| 507 void VisitVariableProxy(VariableProxy* expr) { | 503 void VisitVariableProxy(VariableProxy* expr) { |
| 508 if (in_function_) { | 504 if (scope_ == kFuncScope || scope_ == kInitScope) { |
| 509 Variable* var = expr->var(); | 505 Variable* var = expr->var(); |
| 506 if (VisitStdlibConstant(var)) { |
| 507 return; |
| 508 } |
| 510 LocalType var_type = TypeOf(expr); | 509 LocalType var_type = TypeOf(expr); |
| 511 if (is_set_op_) { | 510 DCHECK_NE(kAstStmt, var_type); |
| 512 is_set_op_ = false; | 511 if (var->IsContextSlot()) { |
| 513 if (var->IsContextSlot()) { | 512 current_function_builder_->EmitWithVarInt( |
| 514 return current_function_builder_->EmitWithVarInt( | 513 kExprLoadGlobal, LookupOrInsertGlobal(var, var_type)); |
| 515 kExprStoreGlobal, LookupOrInsertGlobal(var, var_type)); | |
| 516 } else { | |
| 517 return current_function_builder_->EmitSetLocal( | |
| 518 LookupOrInsertLocal(var, var_type)); | |
| 519 } | |
| 520 } else { | 514 } else { |
| 521 if (VisitStdlibConstant(var)) { | 515 current_function_builder_->EmitGetLocal( |
| 522 return; | 516 LookupOrInsertLocal(var, var_type)); |
| 523 } | |
| 524 if (var->IsContextSlot()) { | |
| 525 return current_function_builder_->EmitWithVarInt( | |
| 526 kExprLoadGlobal, LookupOrInsertGlobal(var, var_type)); | |
| 527 } else { | |
| 528 return current_function_builder_->EmitGetLocal( | |
| 529 LookupOrInsertLocal(var, var_type)); | |
| 530 } | |
| 531 } | 517 } |
| 532 } | 518 } |
| 533 } | 519 } |
| 534 | 520 |
| 535 void VisitLiteral(Literal* expr) { | 521 void VisitLiteral(Literal* expr) { |
| 536 Handle<Object> value = expr->value(); | 522 Handle<Object> value = expr->value(); |
| 537 if (!in_function_ || !value->IsNumber()) { | 523 if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) { |
| 538 return; | 524 return; |
| 539 } | 525 } |
| 540 Type* type = expr->bounds().upper; | 526 Type* type = expr->bounds().upper; |
| 541 if (type->Is(cache_.kAsmSigned)) { | 527 if (type->Is(cache_.kAsmSigned)) { |
| 542 int32_t i = 0; | 528 int32_t i = 0; |
| 543 if (!value->ToInt32(&i)) { | 529 if (!value->ToInt32(&i)) { |
| 544 UNREACHABLE(); | 530 UNREACHABLE(); |
| 545 } | 531 } |
| 546 byte code[] = {WASM_I32V(i)}; | 532 byte code[] = {WASM_I32V(i)}; |
| 547 current_function_builder_->EmitCode(code, sizeof(code)); | 533 current_function_builder_->EmitCode(code, sizeof(code)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 561 UNREACHABLE(); | 547 UNREACHABLE(); |
| 562 } | 548 } |
| 563 } | 549 } |
| 564 | 550 |
| 565 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } | 551 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } |
| 566 | 552 |
| 567 void VisitObjectLiteral(ObjectLiteral* expr) { | 553 void VisitObjectLiteral(ObjectLiteral* expr) { |
| 568 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | 554 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
| 569 for (int i = 0; i < props->length(); ++i) { | 555 for (int i = 0; i < props->length(); ++i) { |
| 570 ObjectLiteralProperty* prop = props->at(i); | 556 ObjectLiteralProperty* prop = props->at(i); |
| 571 DCHECK(marking_exported); | 557 DCHECK_EQ(kExportScope, scope_); |
| 572 VariableProxy* expr = prop->value()->AsVariableProxy(); | 558 VariableProxy* expr = prop->value()->AsVariableProxy(); |
| 573 DCHECK_NOT_NULL(expr); | 559 DCHECK_NOT_NULL(expr); |
| 574 Variable* var = expr->var(); | 560 Variable* var = expr->var(); |
| 575 Literal* name = prop->key()->AsLiteral(); | 561 Literal* name = prop->key()->AsLiteral(); |
| 576 DCHECK_NOT_NULL(name); | 562 DCHECK_NOT_NULL(name); |
| 577 DCHECK(name->IsPropertyName()); | 563 DCHECK(name->IsPropertyName()); |
| 578 const AstRawString* raw_name = name->AsRawPropertyName(); | 564 const AstRawString* raw_name = name->AsRawPropertyName(); |
| 579 if (var->is_function()) { | 565 if (var->is_function()) { |
| 580 uint16_t index = LookupOrInsertFunction(var); | 566 uint16_t index = LookupOrInsertFunction(var); |
| 581 builder_->FunctionAt(index)->Exported(1); | 567 builder_->FunctionAt(index)->Exported(1); |
| 582 builder_->FunctionAt(index) | 568 builder_->FunctionAt(index) |
| 583 ->SetName(raw_name->raw_data(), raw_name->length()); | 569 ->SetName(raw_name->raw_data(), raw_name->length()); |
| 584 } | 570 } |
| 585 } | 571 } |
| 586 } | 572 } |
| 587 | 573 |
| 588 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } | 574 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } |
| 589 | 575 |
| 590 void LoadInitFunction() { | 576 void LoadInitFunction() { |
| 591 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 577 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 592 in_function_ = true; | 578 scope_ = kInitScope; |
| 593 } | 579 } |
| 594 | 580 |
| 595 void UnLoadInitFunction() { | 581 void UnLoadInitFunction() { |
| 596 in_function_ = false; | 582 scope_ = kModuleScope; |
| 597 current_function_builder_ = nullptr; | 583 current_function_builder_ = nullptr; |
| 598 } | 584 } |
| 599 | 585 |
| 600 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 586 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
| 601 FunctionType* func_type = | 587 FunctionType* func_type = |
| 602 funcs->bounds().lower->AsArray()->Element()->AsFunction(); | 588 funcs->bounds().lower->AsArray()->Element()->AsFunction(); |
| 603 LocalType return_type = TypeFrom(func_type->Result()); | 589 LocalType return_type = TypeFrom(func_type->Result()); |
| 604 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 590 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 605 func_type->Arity()); | 591 func_type->Arity()); |
| 606 if (return_type != kAstStmt) { | 592 if (return_type != kAstStmt) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 function->ReturnType(sig->GetReturn()); | 675 function->ReturnType(sig->GetReturn()); |
| 690 } | 676 } |
| 691 for (size_t i = 0; i < sig->parameter_count(); i++) { | 677 for (size_t i = 0; i < sig->parameter_count(); i++) { |
| 692 function->AddParam(sig->GetParam(i)); | 678 function->AddParam(sig->GetParam(i)); |
| 693 } | 679 } |
| 694 return index; | 680 return index; |
| 695 } | 681 } |
| 696 } | 682 } |
| 697 }; | 683 }; |
| 698 | 684 |
| 699 void VisitAssignment(Assignment* expr) { | 685 void EmitAssignmentLhs(Expression* target, MachineType* mtype) { |
| 700 bool in_init = false; | 686 // Match the left hand side of the assignment. |
| 701 if (!in_function_) { | 687 VariableProxy* target_var = target->AsVariableProxy(); |
| 702 BinaryOperation* binop = expr->value()->AsBinaryOperation(); | 688 if (target_var != nullptr) { |
| 703 if (binop != nullptr) { | 689 // Left hand side is a local or a global variable, no code on LHS. |
| 690 return; |
| 691 } |
| 692 |
| 693 Property* target_prop = target->AsProperty(); |
| 694 if (target_prop != nullptr) { |
| 695 // Left hand side is a property access, i.e. the asm.js heap. |
| 696 VisitPropertyAndEmitIndex(target_prop, mtype); |
| 697 return; |
| 698 } |
| 699 |
| 700 if (target_var == nullptr && target_prop == nullptr) { |
| 701 UNREACHABLE(); // invalid assignment. |
| 702 } |
| 703 } |
| 704 |
| 705 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { |
| 706 BinaryOperation* binop = value->AsBinaryOperation(); |
| 707 if (binop != nullptr) { |
| 708 if (scope_ == kInitScope) { |
| 709 // Handle foreign variables in the initialization scope. |
| 704 Property* prop = binop->left()->AsProperty(); | 710 Property* prop = binop->left()->AsProperty(); |
| 705 DCHECK_NOT_NULL(prop); | |
| 706 LoadInitFunction(); | |
| 707 is_set_op_ = true; | |
| 708 RECURSE(Visit(expr->target())); | |
| 709 DCHECK(!is_set_op_); | |
| 710 if (binop->op() == Token::MUL) { | 711 if (binop->op() == Token::MUL) { |
| 711 DCHECK(binop->right()->IsLiteral()); | 712 DCHECK(binop->right()->IsLiteral()); |
| 712 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 713 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
| 713 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 714 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
| 714 VisitForeignVariable(true, prop); | 715 VisitForeignVariable(true, prop); |
| 716 return; |
| 715 } else if (binop->op() == Token::BIT_OR) { | 717 } else if (binop->op() == Token::BIT_OR) { |
| 716 DCHECK(binop->right()->IsLiteral()); | 718 DCHECK(binop->right()->IsLiteral()); |
| 717 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 719 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
| 718 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 720 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
| 719 VisitForeignVariable(false, prop); | 721 VisitForeignVariable(false, prop); |
| 722 return; |
| 720 } else { | 723 } else { |
| 721 UNREACHABLE(); | 724 UNREACHABLE(); |
| 722 } | 725 } |
| 723 UnLoadInitFunction(); | |
| 724 return; | |
| 725 } | 726 } |
| 727 if (MatchBinaryOperation(binop) == kAsIs) { |
| 728 VariableProxy* target_var = target->AsVariableProxy(); |
| 729 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy(); |
| 730 if (target_var != nullptr && effective_value_var != nullptr && |
| 731 target_var->var() == effective_value_var->var()) { |
| 732 *is_nop = true; |
| 733 return; |
| 734 } |
| 735 } |
| 736 } |
| 737 RECURSE(Visit(value)); |
| 738 } |
| 739 |
| 740 void EmitAssignment(Assignment* expr, MachineType mtype) { |
| 741 // Match the left hand side of the assignment. |
| 742 VariableProxy* target_var = expr->target()->AsVariableProxy(); |
| 743 if (target_var != nullptr) { |
| 744 // Left hand side is a local or a global variable. |
| 745 Variable* var = target_var->var(); |
| 746 LocalType var_type = TypeOf(expr); |
| 747 DCHECK_NE(kAstStmt, var_type); |
| 748 if (var->IsContextSlot()) { |
| 749 current_function_builder_->EmitWithVarInt( |
| 750 kExprStoreGlobal, LookupOrInsertGlobal(var, var_type)); |
| 751 } else { |
| 752 current_function_builder_->EmitSetLocal( |
| 753 LookupOrInsertLocal(var, var_type)); |
| 754 } |
| 755 } |
| 756 |
| 757 Property* target_prop = expr->target()->AsProperty(); |
| 758 if (target_prop != nullptr) { |
| 759 // Left hand side is a property access, i.e. the asm.js heap. |
| 760 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && |
| 761 expr->target()->AsProperty()->obj()->bounds().lower->Is( |
| 762 cache_.kFloat32Array)) { |
| 763 current_function_builder_->Emit(kExprF32ConvertF64); |
| 764 } |
| 765 current_function_builder_->EmitWithU8U8( |
| 766 WasmOpcodes::LoadStoreOpcodeOf(mtype, true), 0, 0); |
| 767 } |
| 768 |
| 769 if (target_var == nullptr && target_prop == nullptr) { |
| 770 UNREACHABLE(); // invalid assignment. |
| 771 } |
| 772 } |
| 773 |
| 774 void VisitAssignment(Assignment* expr) { |
| 775 bool as_init = false; |
| 776 if (scope_ == kModuleScope) { |
| 726 Property* prop = expr->value()->AsProperty(); | 777 Property* prop = expr->value()->AsProperty(); |
| 727 if (prop != nullptr) { | 778 if (prop != nullptr) { |
| 728 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 779 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
| 729 if (vp != nullptr && vp->var()->IsParameter() && | 780 if (vp != nullptr && vp->var()->IsParameter() && |
| 730 vp->var()->index() == 1) { | 781 vp->var()->index() == 1) { |
| 731 VariableProxy* target = expr->target()->AsVariableProxy(); | 782 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 732 if (target->bounds().lower->Is(Type::Function())) { | 783 if (target->bounds().lower->Is(Type::Function())) { |
| 733 const AstRawString* name = | 784 const AstRawString* name = |
| 734 prop->key()->AsLiteral()->AsRawPropertyName(); | 785 prop->key()->AsLiteral()->AsRawPropertyName(); |
| 735 imported_function_table_.AddImport(target->var(), name->raw_data(), | 786 imported_function_table_.AddImport(target->var(), name->raw_data(), |
| 736 name->length()); | 787 name->length()); |
| 737 } | 788 } |
| 738 } | 789 } |
| 739 // Property values in module scope don't emit code, so return. | 790 // Property values in module scope don't emit code, so return. |
| 740 return; | 791 return; |
| 741 } | 792 } |
| 742 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 793 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| 743 if (funcs != nullptr && | 794 if (funcs != nullptr && |
| 744 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { | 795 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { |
| 745 VariableProxy* target = expr->target()->AsVariableProxy(); | 796 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 746 DCHECK_NOT_NULL(target); | 797 DCHECK_NOT_NULL(target); |
| 747 AddFunctionTable(target, funcs); | 798 AddFunctionTable(target, funcs); |
| 748 // Only add to the function table. No init needed. | 799 // Only add to the function table. No init needed. |
| 749 return; | 800 return; |
| 750 } | 801 } |
| 751 if (expr->value()->IsCallNew()) { | 802 if (expr->value()->IsCallNew()) { |
| 752 // No init code to emit for CallNew nodes. | 803 // No init code to emit for CallNew nodes. |
| 753 return; | 804 return; |
| 754 } | 805 } |
| 755 in_init = true; | 806 as_init = true; |
| 756 LoadInitFunction(); | |
| 757 } | 807 } |
| 758 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); | 808 |
| 759 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { | 809 if (as_init) LoadInitFunction(); |
| 760 VariableProxy* target_var = expr->target()->AsVariableProxy(); | 810 MachineType mtype; |
| 761 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); | 811 bool is_nop = false; |
| 762 if (target_var != nullptr && effective_value_var != nullptr && | 812 EmitAssignmentLhs(expr->target(), &mtype); |
| 763 target_var->var() == effective_value_var->var()) { | 813 EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); |
| 764 block_size_--; | 814 if (!is_nop) { |
| 765 return; | 815 EmitAssignment(expr, mtype); |
| 766 } | |
| 767 } | 816 } |
| 768 is_set_op_ = true; | 817 if (as_init) UnLoadInitFunction(); |
| 769 RECURSE(Visit(expr->target())); | |
| 770 DCHECK(!is_set_op_); | |
| 771 // Assignment to heapf32 from float64 converts. | |
| 772 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | |
| 773 expr->target()->AsProperty()->obj()->bounds().lower->Is( | |
| 774 cache_.kFloat32Array)) { | |
| 775 current_function_builder_->Emit(kExprF32ConvertF64); | |
| 776 } | |
| 777 RECURSE(Visit(expr->value())); | |
| 778 if (in_init) { | |
| 779 UnLoadInitFunction(); | |
| 780 } | |
| 781 } | 818 } |
| 782 | 819 |
| 783 void VisitYield(Yield* expr) { UNREACHABLE(); } | 820 void VisitYield(Yield* expr) { UNREACHABLE(); } |
| 784 | 821 |
| 785 void VisitThrow(Throw* expr) { UNREACHABLE(); } | 822 void VisitThrow(Throw* expr) { UNREACHABLE(); } |
| 786 | 823 |
| 787 void VisitForeignVariable(bool is_float, Property* expr) { | 824 void VisitForeignVariable(bool is_float, Property* expr) { |
| 788 DCHECK(expr->obj()->AsVariableProxy()); | 825 DCHECK(expr->obj()->AsVariableProxy()); |
| 789 DCHECK(VariableLocation::PARAMETER == | 826 DCHECK(VariableLocation::PARAMETER == |
| 790 expr->obj()->AsVariableProxy()->var()->location()); | 827 expr->obj()->AsVariableProxy()->var()->location()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 809 return; | 846 return; |
| 810 } | 847 } |
| 811 } | 848 } |
| 812 } else { | 849 } else { |
| 813 MaybeHandle<Object> maybe_nvalue = | 850 MaybeHandle<Object> maybe_nvalue = |
| 814 i::Object::ToInt32(isolate_, value); | 851 i::Object::ToInt32(isolate_, value); |
| 815 if (!maybe_nvalue.is_null()) { | 852 if (!maybe_nvalue.is_null()) { |
| 816 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); | 853 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); |
| 817 if (nvalue->IsNumber()) { | 854 if (nvalue->IsNumber()) { |
| 818 int32_t val = static_cast<int32_t>(nvalue->Number()); | 855 int32_t val = static_cast<int32_t>(nvalue->Number()); |
| 819 // TODO(bradnelson): variable size | 856 current_function_builder_->EmitI32Const(val); |
| 820 byte code[] = {WASM_I32V(val)}; | |
| 821 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 822 return; | 857 return; |
| 823 } | 858 } |
| 824 } | 859 } |
| 825 } | 860 } |
| 826 } | 861 } |
| 827 } | 862 } |
| 828 if (is_float) { | 863 if (is_float) { |
| 829 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; | 864 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; |
| 830 current_function_builder_->EmitCode(code, sizeof(code)); | 865 current_function_builder_->EmitCode(code, sizeof(code)); |
| 831 } else { | 866 } else { |
| 832 byte code[] = {WASM_I32V_1(0)}; | 867 byte code[] = {WASM_I32V_1(0)}; |
| 833 current_function_builder_->EmitCode(code, sizeof(code)); | 868 current_function_builder_->EmitCode(code, sizeof(code)); |
| 834 } | 869 } |
| 835 } | 870 } |
| 836 | 871 |
| 837 void VisitProperty(Property* expr) { | 872 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { |
| 838 Expression* obj = expr->obj(); | 873 Expression* obj = expr->obj(); |
| 839 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); | 874 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); |
| 840 Type* type = obj->bounds().lower; | 875 Type* type = obj->bounds().lower; |
| 841 MachineType mtype; | |
| 842 int size; | 876 int size; |
| 843 if (type->Is(cache_.kUint8Array)) { | 877 if (type->Is(cache_.kUint8Array)) { |
| 844 mtype = MachineType::Uint8(); | 878 *mtype = MachineType::Uint8(); |
| 845 size = 1; | 879 size = 1; |
| 846 } else if (type->Is(cache_.kInt8Array)) { | 880 } else if (type->Is(cache_.kInt8Array)) { |
| 847 mtype = MachineType::Int8(); | 881 *mtype = MachineType::Int8(); |
| 848 size = 1; | 882 size = 1; |
| 849 } else if (type->Is(cache_.kUint16Array)) { | 883 } else if (type->Is(cache_.kUint16Array)) { |
| 850 mtype = MachineType::Uint16(); | 884 *mtype = MachineType::Uint16(); |
| 851 size = 2; | 885 size = 2; |
| 852 } else if (type->Is(cache_.kInt16Array)) { | 886 } else if (type->Is(cache_.kInt16Array)) { |
| 853 mtype = MachineType::Int16(); | 887 *mtype = MachineType::Int16(); |
| 854 size = 2; | 888 size = 2; |
| 855 } else if (type->Is(cache_.kUint32Array)) { | 889 } else if (type->Is(cache_.kUint32Array)) { |
| 856 mtype = MachineType::Uint32(); | 890 *mtype = MachineType::Uint32(); |
| 857 size = 4; | 891 size = 4; |
| 858 } else if (type->Is(cache_.kInt32Array)) { | 892 } else if (type->Is(cache_.kInt32Array)) { |
| 859 mtype = MachineType::Int32(); | 893 *mtype = MachineType::Int32(); |
| 860 size = 4; | 894 size = 4; |
| 861 } else if (type->Is(cache_.kUint32Array)) { | 895 } else if (type->Is(cache_.kUint32Array)) { |
| 862 mtype = MachineType::Uint32(); | 896 *mtype = MachineType::Uint32(); |
| 863 size = 4; | 897 size = 4; |
| 864 } else if (type->Is(cache_.kFloat32Array)) { | 898 } else if (type->Is(cache_.kFloat32Array)) { |
| 865 mtype = MachineType::Float32(); | 899 *mtype = MachineType::Float32(); |
| 866 size = 4; | 900 size = 4; |
| 867 } else if (type->Is(cache_.kFloat64Array)) { | 901 } else if (type->Is(cache_.kFloat64Array)) { |
| 868 mtype = MachineType::Float64(); | 902 *mtype = MachineType::Float64(); |
| 869 size = 8; | 903 size = 8; |
| 870 } else { | 904 } else { |
| 871 UNREACHABLE(); | 905 UNREACHABLE(); |
| 872 } | 906 } |
| 873 // TODO(titzer): use special asm-compatibility opcodes? | |
| 874 current_function_builder_->EmitWithU8U8( | |
| 875 WasmOpcodes::LoadStoreOpcodeOf(mtype, is_set_op_), 0, 0); | |
| 876 is_set_op_ = false; | |
| 877 if (size == 1) { | 907 if (size == 1) { |
| 878 // Allow more general expression in byte arrays than the spec | 908 // Allow more general expression in byte arrays than the spec |
| 879 // strictly permits. | 909 // strictly permits. |
| 880 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in | 910 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in |
| 881 // places that strictly should be HEAP8[HEAP32[..]>>0]. | 911 // places that strictly should be HEAP8[HEAP32[..]>>0]. |
| 882 RECURSE(Visit(expr->key())); | 912 RECURSE(Visit(expr->key())); |
| 883 return; | 913 return; |
| 884 } else { | 914 } |
| 885 Literal* value = expr->key()->AsLiteral(); | 915 |
| 886 if (value) { | 916 Literal* value = expr->key()->AsLiteral(); |
| 887 DCHECK(value->raw_value()->IsNumber()); | 917 if (value) { |
| 888 DCHECK_EQ(kAstI32, TypeOf(value)); | 918 DCHECK(value->raw_value()->IsNumber()); |
| 889 int val = static_cast<int>(value->raw_value()->AsNumber()); | 919 DCHECK_EQ(kAstI32, TypeOf(value)); |
| 890 // TODO(bradnelson): variable size | 920 int32_t val = static_cast<int32_t>(value->raw_value()->AsNumber()); |
| 891 byte code[] = {WASM_I32V(val * size)}; | 921 // TODO(titzer): handle overflow here. |
| 892 current_function_builder_->EmitCode(code, sizeof(code)); | 922 current_function_builder_->EmitI32Const(val * size); |
| 893 return; | 923 return; |
| 894 } | 924 } |
| 895 BinaryOperation* binop = expr->key()->AsBinaryOperation(); | 925 BinaryOperation* binop = expr->key()->AsBinaryOperation(); |
| 896 if (binop) { | 926 if (binop) { |
| 897 DCHECK_EQ(Token::SAR, binop->op()); | 927 DCHECK_EQ(Token::SAR, binop->op()); |
| 898 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); | 928 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); |
| 899 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); | 929 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); |
| 900 DCHECK_EQ(size, | 930 DCHECK_EQ(size, |
| 901 1 << static_cast<int>( | 931 1 << static_cast<int>( |
| 902 binop->right()->AsLiteral()->raw_value()->AsNumber())); | 932 binop->right()->AsLiteral()->raw_value()->AsNumber())); |
| 903 // Mask bottom bits to match asm.js behavior. | 933 // Mask bottom bits to match asm.js behavior. |
| 904 current_function_builder_->Emit(kExprI32And); | 934 byte mask = static_cast<byte>(~(size - 1)); |
| 905 byte code[] = {WASM_I8(~(size - 1))}; | 935 RECURSE(Visit(binop->left())); |
| 906 current_function_builder_->EmitCode(code, sizeof(code)); | 936 current_function_builder_->EmitWithU8(kExprI8Const, mask); |
| 907 RECURSE(Visit(binop->left())); | 937 current_function_builder_->Emit(kExprI32And); |
| 908 return; | 938 return; |
| 909 } | |
| 910 } | 939 } |
| 911 UNREACHABLE(); | 940 UNREACHABLE(); |
| 912 } | 941 } |
| 913 | 942 |
| 943 void VisitProperty(Property* expr) { |
| 944 MachineType mtype; |
| 945 VisitPropertyAndEmitIndex(expr, &mtype); |
| 946 current_function_builder_->EmitWithU8U8( |
| 947 WasmOpcodes::LoadStoreOpcodeOf(mtype, false), 0, 0); |
| 948 } |
| 949 |
| 914 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { | 950 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { |
| 915 Variable* var = expr->var(); | 951 Variable* var = expr->var(); |
| 916 AsmTyper::StandardMember standard_object = | 952 AsmTyper::StandardMember standard_object = |
| 917 typer_->VariableAsStandardMember(var); | 953 typer_->VariableAsStandardMember(var); |
| 918 ZoneList<Expression*>* args = call->arguments(); | 954 ZoneList<Expression*>* args = call->arguments(); |
| 919 LocalType call_type = TypeOf(call); | 955 LocalType call_type = TypeOf(call); |
| 956 |
| 920 switch (standard_object) { | 957 switch (standard_object) { |
| 921 case AsmTyper::kNone: { | 958 case AsmTyper::kNone: { |
| 922 return false; | 959 return false; |
| 923 } | 960 } |
| 924 case AsmTyper::kMathAcos: { | 961 case AsmTyper::kMathAcos: { |
| 962 VisitCallArgs(call); |
| 925 DCHECK_EQ(kAstF64, call_type); | 963 DCHECK_EQ(kAstF64, call_type); |
| 926 current_function_builder_->Emit(kExprF64Acos); | 964 current_function_builder_->Emit(kExprF64Acos); |
| 927 break; | 965 break; |
| 928 } | 966 } |
| 929 case AsmTyper::kMathAsin: { | 967 case AsmTyper::kMathAsin: { |
| 968 VisitCallArgs(call); |
| 930 DCHECK_EQ(kAstF64, call_type); | 969 DCHECK_EQ(kAstF64, call_type); |
| 931 current_function_builder_->Emit(kExprF64Asin); | 970 current_function_builder_->Emit(kExprF64Asin); |
| 932 break; | 971 break; |
| 933 } | 972 } |
| 934 case AsmTyper::kMathAtan: { | 973 case AsmTyper::kMathAtan: { |
| 974 VisitCallArgs(call); |
| 935 DCHECK_EQ(kAstF64, call_type); | 975 DCHECK_EQ(kAstF64, call_type); |
| 936 current_function_builder_->Emit(kExprF64Atan); | 976 current_function_builder_->Emit(kExprF64Atan); |
| 937 break; | 977 break; |
| 938 } | 978 } |
| 939 case AsmTyper::kMathCos: { | 979 case AsmTyper::kMathCos: { |
| 980 VisitCallArgs(call); |
| 940 DCHECK_EQ(kAstF64, call_type); | 981 DCHECK_EQ(kAstF64, call_type); |
| 941 current_function_builder_->Emit(kExprF64Cos); | 982 current_function_builder_->Emit(kExprF64Cos); |
| 942 break; | 983 break; |
| 943 } | 984 } |
| 944 case AsmTyper::kMathSin: { | 985 case AsmTyper::kMathSin: { |
| 986 VisitCallArgs(call); |
| 945 DCHECK_EQ(kAstF64, call_type); | 987 DCHECK_EQ(kAstF64, call_type); |
| 946 current_function_builder_->Emit(kExprF64Sin); | 988 current_function_builder_->Emit(kExprF64Sin); |
| 947 break; | 989 break; |
| 948 } | 990 } |
| 949 case AsmTyper::kMathTan: { | 991 case AsmTyper::kMathTan: { |
| 992 VisitCallArgs(call); |
| 950 DCHECK_EQ(kAstF64, call_type); | 993 DCHECK_EQ(kAstF64, call_type); |
| 951 current_function_builder_->Emit(kExprF64Tan); | 994 current_function_builder_->Emit(kExprF64Tan); |
| 952 break; | 995 break; |
| 953 } | 996 } |
| 954 case AsmTyper::kMathExp: { | 997 case AsmTyper::kMathExp: { |
| 998 VisitCallArgs(call); |
| 955 DCHECK_EQ(kAstF64, call_type); | 999 DCHECK_EQ(kAstF64, call_type); |
| 956 current_function_builder_->Emit(kExprF64Exp); | 1000 current_function_builder_->Emit(kExprF64Exp); |
| 957 break; | 1001 break; |
| 958 } | 1002 } |
| 959 case AsmTyper::kMathLog: { | 1003 case AsmTyper::kMathLog: { |
| 1004 VisitCallArgs(call); |
| 960 DCHECK_EQ(kAstF64, call_type); | 1005 DCHECK_EQ(kAstF64, call_type); |
| 961 current_function_builder_->Emit(kExprF64Log); | 1006 current_function_builder_->Emit(kExprF64Log); |
| 962 break; | 1007 break; |
| 963 } | 1008 } |
| 964 case AsmTyper::kMathCeil: { | 1009 case AsmTyper::kMathCeil: { |
| 1010 VisitCallArgs(call); |
| 965 if (call_type == kAstF32) { | 1011 if (call_type == kAstF32) { |
| 966 current_function_builder_->Emit(kExprF32Ceil); | 1012 current_function_builder_->Emit(kExprF32Ceil); |
| 967 } else if (call_type == kAstF64) { | 1013 } else if (call_type == kAstF64) { |
| 968 current_function_builder_->Emit(kExprF64Ceil); | 1014 current_function_builder_->Emit(kExprF64Ceil); |
| 969 } else { | 1015 } else { |
| 970 UNREACHABLE(); | 1016 UNREACHABLE(); |
| 971 } | 1017 } |
| 972 break; | 1018 break; |
| 973 } | 1019 } |
| 974 case AsmTyper::kMathFloor: { | 1020 case AsmTyper::kMathFloor: { |
| 1021 VisitCallArgs(call); |
| 975 if (call_type == kAstF32) { | 1022 if (call_type == kAstF32) { |
| 976 current_function_builder_->Emit(kExprF32Floor); | 1023 current_function_builder_->Emit(kExprF32Floor); |
| 977 } else if (call_type == kAstF64) { | 1024 } else if (call_type == kAstF64) { |
| 978 current_function_builder_->Emit(kExprF64Floor); | 1025 current_function_builder_->Emit(kExprF64Floor); |
| 979 } else { | 1026 } else { |
| 980 UNREACHABLE(); | 1027 UNREACHABLE(); |
| 981 } | 1028 } |
| 982 break; | 1029 break; |
| 983 } | 1030 } |
| 984 case AsmTyper::kMathSqrt: { | 1031 case AsmTyper::kMathSqrt: { |
| 1032 VisitCallArgs(call); |
| 985 if (call_type == kAstF32) { | 1033 if (call_type == kAstF32) { |
| 986 current_function_builder_->Emit(kExprF32Sqrt); | 1034 current_function_builder_->Emit(kExprF32Sqrt); |
| 987 } else if (call_type == kAstF64) { | 1035 } else if (call_type == kAstF64) { |
| 988 current_function_builder_->Emit(kExprF64Sqrt); | 1036 current_function_builder_->Emit(kExprF64Sqrt); |
| 989 } else { | 1037 } else { |
| 990 UNREACHABLE(); | 1038 UNREACHABLE(); |
| 991 } | 1039 } |
| 992 break; | 1040 break; |
| 993 } | 1041 } |
| 994 case AsmTyper::kMathAbs: { | 1042 case AsmTyper::kMathAbs: { |
| 995 // TODO(bradnelson): Should this be cast to float? | |
| 996 if (call_type == kAstI32) { | 1043 if (call_type == kAstI32) { |
| 997 current_function_builder_->Emit(kExprIfElse); | 1044 uint16_t tmp = current_function_builder_->AddLocal(kAstI32); |
| 998 current_function_builder_->Emit(kExprI32LtS); | 1045 |
| 999 Visit(args->at(0)); | 1046 // if set_local(tmp, x) < 0 |
| 1047 Visit(call->arguments()->at(0)); |
| 1048 current_function_builder_->EmitSetLocal(tmp); |
| 1000 byte code[] = {WASM_I8(0)}; | 1049 byte code[] = {WASM_I8(0)}; |
| 1001 current_function_builder_->EmitCode(code, sizeof(code)); | 1050 current_function_builder_->EmitCode(code, sizeof(code)); |
| 1051 current_function_builder_->Emit(kExprI32LtS); |
| 1052 current_function_builder_->Emit(kExprIf); |
| 1053 |
| 1054 // then (0 - tmp) |
| 1055 current_function_builder_->EmitCode(code, sizeof(code)); |
| 1056 current_function_builder_->EmitGetLocal(tmp); |
| 1002 current_function_builder_->Emit(kExprI32Sub); | 1057 current_function_builder_->Emit(kExprI32Sub); |
| 1003 current_function_builder_->EmitCode(code, sizeof(code)); | 1058 |
| 1004 Visit(args->at(0)); | 1059 // else tmp |
| 1060 current_function_builder_->Emit(kExprElse); |
| 1061 current_function_builder_->EmitGetLocal(tmp); |
| 1062 // end |
| 1063 current_function_builder_->Emit(kExprEnd); |
| 1064 |
| 1005 } else if (call_type == kAstF32) { | 1065 } else if (call_type == kAstF32) { |
| 1066 VisitCallArgs(call); |
| 1006 current_function_builder_->Emit(kExprF32Abs); | 1067 current_function_builder_->Emit(kExprF32Abs); |
| 1007 } else if (call_type == kAstF64) { | 1068 } else if (call_type == kAstF64) { |
| 1069 VisitCallArgs(call); |
| 1008 current_function_builder_->Emit(kExprF64Abs); | 1070 current_function_builder_->Emit(kExprF64Abs); |
| 1009 } else { | 1071 } else { |
| 1010 UNREACHABLE(); | 1072 UNREACHABLE(); |
| 1011 } | 1073 } |
| 1012 break; | 1074 break; |
| 1013 } | 1075 } |
| 1014 case AsmTyper::kMathMin: { | 1076 case AsmTyper::kMathMin: { |
| 1015 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. | 1077 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. |
| 1016 if (call_type == kAstI32) { | 1078 if (call_type == kAstI32) { |
| 1017 current_function_builder_->Emit(kExprIfElse); | 1079 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
| 1080 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); |
| 1081 |
| 1082 // if set_local(tmp_x, x) < set_local(tmp_y, y) |
| 1083 Visit(call->arguments()->at(0)); |
| 1084 current_function_builder_->EmitSetLocal(tmp_x); |
| 1085 |
| 1086 Visit(call->arguments()->at(1)); |
| 1087 current_function_builder_->EmitSetLocal(tmp_y); |
| 1088 |
| 1018 current_function_builder_->Emit(kExprI32LeS); | 1089 current_function_builder_->Emit(kExprI32LeS); |
| 1019 Visit(args->at(0)); | 1090 current_function_builder_->Emit(kExprIf); |
| 1020 Visit(args->at(1)); | 1091 |
| 1092 // then tmp_x |
| 1093 current_function_builder_->EmitGetLocal(tmp_x); |
| 1094 |
| 1095 // else tmp_y |
| 1096 current_function_builder_->Emit(kExprElse); |
| 1097 current_function_builder_->EmitGetLocal(tmp_y); |
| 1098 current_function_builder_->Emit(kExprEnd); |
| 1099 |
| 1021 } else if (call_type == kAstF32) { | 1100 } else if (call_type == kAstF32) { |
| 1101 VisitCallArgs(call); |
| 1022 current_function_builder_->Emit(kExprF32Min); | 1102 current_function_builder_->Emit(kExprF32Min); |
| 1023 } else if (call_type == kAstF64) { | 1103 } else if (call_type == kAstF64) { |
| 1104 VisitCallArgs(call); |
| 1024 current_function_builder_->Emit(kExprF64Min); | 1105 current_function_builder_->Emit(kExprF64Min); |
| 1025 } else { | 1106 } else { |
| 1026 UNREACHABLE(); | 1107 UNREACHABLE(); |
| 1027 } | 1108 } |
| 1028 break; | 1109 break; |
| 1029 } | 1110 } |
| 1030 case AsmTyper::kMathMax: { | 1111 case AsmTyper::kMathMax: { |
| 1031 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. | 1112 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. |
| 1032 if (call_type == kAstI32) { | 1113 if (call_type == kAstI32) { |
| 1033 current_function_builder_->Emit(kExprIfElse); | 1114 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
| 1034 current_function_builder_->Emit(kExprI32GtS); | 1115 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); |
| 1035 Visit(args->at(0)); | 1116 |
| 1036 Visit(args->at(1)); | 1117 // if set_local(tmp_x, x) < set_local(tmp_y, y) |
| 1118 Visit(call->arguments()->at(0)); |
| 1119 |
| 1120 current_function_builder_->EmitSetLocal(tmp_x); |
| 1121 |
| 1122 Visit(call->arguments()->at(1)); |
| 1123 current_function_builder_->EmitSetLocal(tmp_y); |
| 1124 |
| 1125 current_function_builder_->Emit(kExprI32LeS); |
| 1126 current_function_builder_->Emit(kExprIf); |
| 1127 |
| 1128 // then tmp_y |
| 1129 current_function_builder_->EmitGetLocal(tmp_y); |
| 1130 |
| 1131 // else tmp_x |
| 1132 current_function_builder_->Emit(kExprElse); |
| 1133 current_function_builder_->EmitGetLocal(tmp_x); |
| 1134 current_function_builder_->Emit(kExprEnd); |
| 1135 |
| 1037 } else if (call_type == kAstF32) { | 1136 } else if (call_type == kAstF32) { |
| 1137 VisitCallArgs(call); |
| 1038 current_function_builder_->Emit(kExprF32Max); | 1138 current_function_builder_->Emit(kExprF32Max); |
| 1039 } else if (call_type == kAstF64) { | 1139 } else if (call_type == kAstF64) { |
| 1140 VisitCallArgs(call); |
| 1040 current_function_builder_->Emit(kExprF64Max); | 1141 current_function_builder_->Emit(kExprF64Max); |
| 1041 } else { | 1142 } else { |
| 1042 UNREACHABLE(); | 1143 UNREACHABLE(); |
| 1043 } | 1144 } |
| 1044 break; | 1145 break; |
| 1045 } | 1146 } |
| 1046 case AsmTyper::kMathAtan2: { | 1147 case AsmTyper::kMathAtan2: { |
| 1148 VisitCallArgs(call); |
| 1047 DCHECK_EQ(kAstF64, call_type); | 1149 DCHECK_EQ(kAstF64, call_type); |
| 1048 current_function_builder_->Emit(kExprF64Atan2); | 1150 current_function_builder_->Emit(kExprF64Atan2); |
| 1049 break; | 1151 break; |
| 1050 } | 1152 } |
| 1051 case AsmTyper::kMathPow: { | 1153 case AsmTyper::kMathPow: { |
| 1154 VisitCallArgs(call); |
| 1052 DCHECK_EQ(kAstF64, call_type); | 1155 DCHECK_EQ(kAstF64, call_type); |
| 1053 current_function_builder_->Emit(kExprF64Pow); | 1156 current_function_builder_->Emit(kExprF64Pow); |
| 1054 break; | 1157 break; |
| 1055 } | 1158 } |
| 1056 case AsmTyper::kMathImul: { | 1159 case AsmTyper::kMathImul: { |
| 1160 VisitCallArgs(call); |
| 1057 current_function_builder_->Emit(kExprI32Mul); | 1161 current_function_builder_->Emit(kExprI32Mul); |
| 1058 break; | 1162 break; |
| 1059 } | 1163 } |
| 1060 case AsmTyper::kMathFround: { | 1164 case AsmTyper::kMathFround: { |
| 1061 DCHECK(args->length() == 1); | 1165 DCHECK(args->length() == 1); |
| 1062 Literal* literal = args->at(0)->AsLiteral(); | 1166 Literal* literal = args->at(0)->AsLiteral(); |
| 1063 if (literal != nullptr) { | 1167 if (literal != nullptr) { |
| 1168 // constant fold Math.fround(#const); |
| 1064 if (literal->raw_value()->IsNumber()) { | 1169 if (literal->raw_value()->IsNumber()) { |
| 1065 float val = static_cast<float>(literal->raw_value()->AsNumber()); | 1170 float val = static_cast<float>(literal->raw_value()->AsNumber()); |
| 1066 byte code[] = {WASM_F32(val)}; | 1171 byte code[] = {WASM_F32(val)}; |
| 1067 current_function_builder_->EmitCode(code, sizeof(code)); | 1172 current_function_builder_->EmitCode(code, sizeof(code)); |
| 1068 return true; | 1173 return true; |
| 1069 } | 1174 } |
| 1070 } | 1175 } |
| 1176 VisitCallArgs(call); |
| 1071 switch (TypeIndexOf(args->at(0))) { | 1177 switch (TypeIndexOf(args->at(0))) { |
| 1072 case kInt32: | 1178 case kInt32: |
| 1073 case kFixnum: | 1179 case kFixnum: |
| 1074 current_function_builder_->Emit(kExprF32SConvertI32); | 1180 current_function_builder_->Emit(kExprF32SConvertI32); |
| 1075 break; | 1181 break; |
| 1076 case kUint32: | 1182 case kUint32: |
| 1077 current_function_builder_->Emit(kExprF32UConvertI32); | 1183 current_function_builder_->Emit(kExprF32UConvertI32); |
| 1078 break; | 1184 break; |
| 1079 case kFloat32: | 1185 case kFloat32: |
| 1080 break; | 1186 break; |
| 1081 case kFloat64: | 1187 case kFloat64: |
| 1082 current_function_builder_->Emit(kExprF32ConvertF64); | 1188 current_function_builder_->Emit(kExprF32ConvertF64); |
| 1083 break; | 1189 break; |
| 1084 default: | 1190 default: |
| 1085 UNREACHABLE(); | 1191 UNREACHABLE(); |
| 1086 } | 1192 } |
| 1087 break; | 1193 break; |
| 1088 } | 1194 } |
| 1089 default: { | 1195 default: { |
| 1090 UNREACHABLE(); | 1196 UNREACHABLE(); |
| 1091 break; | 1197 break; |
| 1092 } | 1198 } |
| 1093 } | 1199 } |
| 1094 VisitCallArgs(call); | |
| 1095 return true; | 1200 return true; |
| 1096 } | 1201 } |
| 1097 | 1202 |
| 1098 void VisitCallArgs(Call* expr) { | 1203 void VisitCallArgs(Call* expr) { |
| 1099 ZoneList<Expression*>* args = expr->arguments(); | 1204 ZoneList<Expression*>* args = expr->arguments(); |
| 1100 for (int i = 0; i < args->length(); ++i) { | 1205 for (int i = 0; i < args->length(); ++i) { |
| 1101 Expression* arg = args->at(i); | 1206 Expression* arg = args->at(i); |
| 1102 RECURSE(Visit(arg)); | 1207 RECURSE(Visit(arg)); |
| 1103 } | 1208 } |
| 1104 } | 1209 } |
| 1105 | 1210 |
| 1106 void VisitCall(Call* expr) { | 1211 void VisitCall(Call* expr) { |
| 1107 Call::CallType call_type = expr->GetCallType(isolate_); | 1212 Call::CallType call_type = expr->GetCallType(isolate_); |
| 1108 switch (call_type) { | 1213 switch (call_type) { |
| 1109 case Call::OTHER_CALL: { | 1214 case Call::OTHER_CALL: { |
| 1110 DCHECK(in_function_); | 1215 DCHECK_EQ(kFuncScope, scope_); |
| 1111 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1216 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 1112 if (proxy != nullptr) { | 1217 if (proxy != nullptr) { |
| 1113 if (VisitStdlibFunction(expr, proxy)) { | 1218 if (VisitStdlibFunction(expr, proxy)) { |
| 1114 return; | 1219 return; |
| 1115 } | 1220 } |
| 1116 } | 1221 } |
| 1117 uint16_t index; | 1222 uint16_t index; |
| 1118 VariableProxy* vp = expr->expression()->AsVariableProxy(); | 1223 VariableProxy* vp = expr->expression()->AsVariableProxy(); |
| 1119 if (vp != nullptr && | 1224 if (vp != nullptr && |
| 1120 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { | 1225 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { |
| 1121 LocalType return_type = TypeOf(expr); | 1226 LocalType return_type = TypeOf(expr); |
| 1122 ZoneList<Expression*>* args = expr->arguments(); | 1227 ZoneList<Expression*>* args = expr->arguments(); |
| 1123 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1228 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 1124 args->length()); | 1229 args->length()); |
| 1125 if (return_type != kAstStmt) { | 1230 if (return_type != kAstStmt) { |
| 1126 sig.AddReturn(return_type); | 1231 sig.AddReturn(return_type); |
| 1127 } | 1232 } |
| 1128 for (int i = 0; i < args->length(); i++) { | 1233 for (int i = 0; i < args->length(); i++) { |
| 1129 sig.AddParam(TypeOf(args->at(i))); | 1234 sig.AddParam(TypeOf(args->at(i))); |
| 1130 } | 1235 } |
| 1131 index = | 1236 index = |
| 1132 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); | 1237 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); |
| 1133 } else { | 1238 } else { |
| 1134 index = LookupOrInsertFunction(vp->var()); | 1239 index = LookupOrInsertFunction(vp->var()); |
| 1135 } | 1240 } |
| 1241 VisitCallArgs(expr); |
| 1136 current_function_builder_->Emit(kExprCallFunction); | 1242 current_function_builder_->Emit(kExprCallFunction); |
| 1243 current_function_builder_->EmitVarInt(expr->arguments()->length()); |
| 1137 current_function_builder_->EmitVarInt(index); | 1244 current_function_builder_->EmitVarInt(index); |
| 1138 break; | 1245 break; |
| 1139 } | 1246 } |
| 1140 case Call::KEYED_PROPERTY_CALL: { | 1247 case Call::KEYED_PROPERTY_CALL: { |
| 1141 DCHECK(in_function_); | 1248 DCHECK_EQ(kFuncScope, scope_); |
| 1142 Property* p = expr->expression()->AsProperty(); | 1249 Property* p = expr->expression()->AsProperty(); |
| 1143 DCHECK_NOT_NULL(p); | 1250 DCHECK_NOT_NULL(p); |
| 1144 VariableProxy* var = p->obj()->AsVariableProxy(); | 1251 VariableProxy* var = p->obj()->AsVariableProxy(); |
| 1145 DCHECK_NOT_NULL(var); | 1252 DCHECK_NOT_NULL(var); |
| 1146 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 1253 FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
| 1147 current_function_builder_->EmitWithVarInt(kExprCallIndirect, | 1254 RECURSE(Visit(p->key())); |
| 1148 indices->signature_index); | 1255 current_function_builder_->EmitI32Const(indices->start_index); |
| 1149 current_function_builder_->Emit(kExprI32Add); | 1256 current_function_builder_->Emit(kExprI32Add); |
| 1150 // TODO(bradnelson): variable size | 1257 VisitCallArgs(expr); |
| 1151 byte code[] = {WASM_I32V(indices->start_index)}; | 1258 current_function_builder_->Emit(kExprCallIndirect); |
| 1152 current_function_builder_->EmitCode(code, sizeof(code)); | 1259 current_function_builder_->EmitVarInt(expr->arguments()->length()); |
| 1153 RECURSE(Visit(p->key())); | 1260 current_function_builder_->EmitVarInt(indices->signature_index); |
| 1154 break; | 1261 break; |
| 1155 } | 1262 } |
| 1156 default: | 1263 default: |
| 1157 UNREACHABLE(); | 1264 UNREACHABLE(); |
| 1158 } | 1265 } |
| 1159 VisitCallArgs(expr); | |
| 1160 } | 1266 } |
| 1161 | 1267 |
| 1162 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } | 1268 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } |
| 1163 | 1269 |
| 1164 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } | 1270 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } |
| 1165 | 1271 |
| 1166 void VisitUnaryOperation(UnaryOperation* expr) { | 1272 void VisitUnaryOperation(UnaryOperation* expr) { |
| 1273 RECURSE(Visit(expr->expression())); |
| 1167 switch (expr->op()) { | 1274 switch (expr->op()) { |
| 1168 case Token::NOT: { | 1275 case Token::NOT: { |
| 1169 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); | 1276 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); |
| 1170 current_function_builder_->Emit(kExprI32Eqz); | 1277 current_function_builder_->Emit(kExprI32Eqz); |
| 1171 break; | 1278 break; |
| 1172 } | 1279 } |
| 1173 default: | 1280 default: |
| 1174 UNREACHABLE(); | 1281 UNREACHABLE(); |
| 1175 } | 1282 } |
| 1176 RECURSE(Visit(expr->expression())); | |
| 1177 } | 1283 } |
| 1178 | 1284 |
| 1179 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } | 1285 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } |
| 1180 | 1286 |
| 1181 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, | 1287 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, |
| 1182 int32_t val) { | 1288 int32_t val) { |
| 1183 DCHECK_NOT_NULL(expr->right()); | 1289 DCHECK_NOT_NULL(expr->right()); |
| 1184 if (expr->op() == op && expr->right()->IsLiteral() && | 1290 if (expr->op() == op && expr->right()->IsLiteral() && |
| 1185 TypeOf(expr) == kAstI32) { | 1291 TypeOf(expr) == kAstI32) { |
| 1186 Literal* right = expr->right()->AsLiteral(); | 1292 Literal* right = expr->right()->AsLiteral(); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1312 if (expr->op() == Token::BIT_XOR) { | 1418 if (expr->op() == Token::BIT_XOR) { |
| 1313 return expr->left()->AsBinaryOperation()->left(); | 1419 return expr->left()->AsBinaryOperation()->left(); |
| 1314 } else { | 1420 } else { |
| 1315 return expr->left(); | 1421 return expr->left(); |
| 1316 } | 1422 } |
| 1317 } | 1423 } |
| 1318 | 1424 |
| 1319 void VisitBinaryOperation(BinaryOperation* expr) { | 1425 void VisitBinaryOperation(BinaryOperation* expr) { |
| 1320 ConvertOperation convertOperation = MatchBinaryOperation(expr); | 1426 ConvertOperation convertOperation = MatchBinaryOperation(expr); |
| 1321 if (convertOperation == kToDouble) { | 1427 if (convertOperation == kToDouble) { |
| 1428 RECURSE(Visit(expr->left())); |
| 1322 TypeIndex type = TypeIndexOf(expr->left()); | 1429 TypeIndex type = TypeIndexOf(expr->left()); |
| 1323 if (type == kInt32 || type == kFixnum) { | 1430 if (type == kInt32 || type == kFixnum) { |
| 1324 current_function_builder_->Emit(kExprF64SConvertI32); | 1431 current_function_builder_->Emit(kExprF64SConvertI32); |
| 1325 } else if (type == kUint32) { | 1432 } else if (type == kUint32) { |
| 1326 current_function_builder_->Emit(kExprF64UConvertI32); | 1433 current_function_builder_->Emit(kExprF64UConvertI32); |
| 1327 } else if (type == kFloat32) { | 1434 } else if (type == kFloat32) { |
| 1328 current_function_builder_->Emit(kExprF64ConvertF32); | 1435 current_function_builder_->Emit(kExprF64ConvertF32); |
| 1329 } else { | 1436 } else { |
| 1330 UNREACHABLE(); | 1437 UNREACHABLE(); |
| 1331 } | 1438 } |
| 1332 RECURSE(Visit(expr->left())); | |
| 1333 } else if (convertOperation == kToInt) { | 1439 } else if (convertOperation == kToInt) { |
| 1440 RECURSE(Visit(GetLeft(expr))); |
| 1334 TypeIndex type = TypeIndexOf(GetLeft(expr)); | 1441 TypeIndex type = TypeIndexOf(GetLeft(expr)); |
| 1335 if (type == kFloat32) { | 1442 if (type == kFloat32) { |
| 1336 current_function_builder_->Emit(kExprI32SConvertF32); | 1443 current_function_builder_->Emit(kExprI32SConvertF32); |
| 1337 } else if (type == kFloat64) { | 1444 } else if (type == kFloat64) { |
| 1338 current_function_builder_->Emit(kExprI32SConvertF64); | 1445 current_function_builder_->Emit(kExprI32SConvertF64); |
| 1339 } else { | 1446 } else { |
| 1340 UNREACHABLE(); | 1447 UNREACHABLE(); |
| 1341 } | 1448 } |
| 1342 RECURSE(Visit(GetLeft(expr))); | |
| 1343 } else if (convertOperation == kAsIs) { | 1449 } else if (convertOperation == kAsIs) { |
| 1344 RECURSE(Visit(GetLeft(expr))); | 1450 RECURSE(Visit(GetLeft(expr))); |
| 1345 } else { | 1451 } else { |
| 1452 if (expr->op() == Token::COMMA) { |
| 1453 current_function_builder_->Emit(kExprBlock); |
| 1454 } |
| 1455 |
| 1456 RECURSE(Visit(expr->left())); |
| 1457 RECURSE(Visit(expr->right())); |
| 1458 |
| 1459 if (expr->op() == Token::COMMA) { |
| 1460 current_function_builder_->Emit(kExprEnd); |
| 1461 } |
| 1462 |
| 1346 switch (expr->op()) { | 1463 switch (expr->op()) { |
| 1347 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); | 1464 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); |
| 1348 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); | 1465 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); |
| 1349 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); | 1466 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); |
| 1350 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); | 1467 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); |
| 1351 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); | 1468 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); |
| 1352 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); | 1469 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); |
| 1353 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); | 1470 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); |
| 1354 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); | 1471 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); |
| 1355 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); | 1472 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); |
| 1356 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); | 1473 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); |
| 1357 case Token::MOD: { | 1474 case Token::MOD: { |
| 1358 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); | 1475 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); |
| 1359 if (type == kInt32) { | 1476 if (type == kInt32) { |
| 1360 current_function_builder_->Emit(kExprI32RemS); | 1477 current_function_builder_->Emit(kExprI32RemS); |
| 1361 } else if (type == kUint32) { | 1478 } else if (type == kUint32) { |
| 1362 current_function_builder_->Emit(kExprI32RemU); | 1479 current_function_builder_->Emit(kExprI32RemU); |
| 1363 } else if (type == kFloat64) { | 1480 } else if (type == kFloat64) { |
| 1364 current_function_builder_->Emit(kExprF64Mod); | 1481 current_function_builder_->Emit(kExprF64Mod); |
| 1365 return; | 1482 return; |
| 1366 } else { | 1483 } else { |
| 1367 UNREACHABLE(); | 1484 UNREACHABLE(); |
| 1368 } | 1485 } |
| 1369 break; | 1486 break; |
| 1370 } | 1487 } |
| 1371 case Token::COMMA: { | 1488 case Token::COMMA: { |
| 1372 current_function_builder_->EmitWithVarInt(kExprBlock, 2); | |
| 1373 break; | 1489 break; |
| 1374 } | 1490 } |
| 1375 default: | 1491 default: |
| 1376 UNREACHABLE(); | 1492 UNREACHABLE(); |
| 1377 } | 1493 } |
| 1378 RECURSE(Visit(expr->left())); | |
| 1379 RECURSE(Visit(expr->right())); | |
| 1380 } | 1494 } |
| 1381 } | 1495 } |
| 1382 | 1496 |
| 1383 void VisitCompareOperation(CompareOperation* expr) { | 1497 void VisitCompareOperation(CompareOperation* expr) { |
| 1498 RECURSE(Visit(expr->left())); |
| 1499 RECURSE(Visit(expr->right())); |
| 1384 switch (expr->op()) { | 1500 switch (expr->op()) { |
| 1385 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); | 1501 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); |
| 1386 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); | 1502 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); |
| 1387 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); | 1503 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); |
| 1388 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); | 1504 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); |
| 1389 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); | 1505 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); |
| 1390 default: | 1506 default: |
| 1391 UNREACHABLE(); | 1507 UNREACHABLE(); |
| 1392 } | 1508 } |
| 1393 RECURSE(Visit(expr->left())); | |
| 1394 RECURSE(Visit(expr->right())); | |
| 1395 } | 1509 } |
| 1396 | 1510 |
| 1397 #undef BINOP_CASE | 1511 #undef BINOP_CASE |
| 1398 #undef NON_SIGNED_INT_BINOP | 1512 #undef NON_SIGNED_INT_BINOP |
| 1399 #undef SIGNED_BINOP | 1513 #undef SIGNED_BINOP |
| 1400 #undef NON_SIGNED_BINOP | 1514 #undef NON_SIGNED_BINOP |
| 1401 | 1515 |
| 1402 enum TypeIndex { | 1516 enum TypeIndex { |
| 1403 kInt32 = 0, | 1517 kInt32 = 0, |
| 1404 kUint32 = 1, | 1518 kUint32 = 1, |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1546 } else { | 1660 } else { |
| 1547 return kAstStmt; | 1661 return kAstStmt; |
| 1548 } | 1662 } |
| 1549 } | 1663 } |
| 1550 | 1664 |
| 1551 Zone* zone() { return zone_; } | 1665 Zone* zone() { return zone_; } |
| 1552 | 1666 |
| 1553 ZoneHashMap local_variables_; | 1667 ZoneHashMap local_variables_; |
| 1554 ZoneHashMap functions_; | 1668 ZoneHashMap functions_; |
| 1555 ZoneHashMap global_variables_; | 1669 ZoneHashMap global_variables_; |
| 1556 bool in_function_; | 1670 AsmScope scope_; |
| 1557 bool is_set_op_; | |
| 1558 bool marking_exported; | |
| 1559 WasmModuleBuilder* builder_; | 1671 WasmModuleBuilder* builder_; |
| 1560 WasmFunctionBuilder* current_function_builder_; | 1672 WasmFunctionBuilder* current_function_builder_; |
| 1561 FunctionLiteral* literal_; | 1673 FunctionLiteral* literal_; |
| 1562 Isolate* isolate_; | 1674 Isolate* isolate_; |
| 1563 Zone* zone_; | 1675 Zone* zone_; |
| 1564 Handle<Object> foreign_; | 1676 Handle<Object> foreign_; |
| 1565 AsmTyper* typer_; | 1677 AsmTyper* typer_; |
| 1566 TypeCache const& cache_; | 1678 TypeCache const& cache_; |
| 1567 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1679 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
| 1568 int block_size_; | |
| 1569 uint16_t init_function_index_; | 1680 uint16_t init_function_index_; |
| 1570 uint32_t next_table_index_; | 1681 uint32_t next_table_index_; |
| 1571 ZoneHashMap function_tables_; | 1682 ZoneHashMap function_tables_; |
| 1572 ImportedFunctionTable imported_function_table_; | 1683 ImportedFunctionTable imported_function_table_; |
| 1573 | 1684 |
| 1574 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1685 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 1575 | 1686 |
| 1576 private: | 1687 private: |
| 1577 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1688 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
| 1578 }; | 1689 }; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1590 // that zone in constructor may be thrown away once wasm module is written. | 1701 // that zone in constructor may be thrown away once wasm module is written. |
| 1591 WasmModuleIndex* AsmWasmBuilder::Run() { | 1702 WasmModuleIndex* AsmWasmBuilder::Run() { |
| 1592 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); | 1703 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); |
| 1593 impl.Compile(); | 1704 impl.Compile(); |
| 1594 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1705 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
| 1595 return writer->WriteTo(zone_); | 1706 return writer->WriteTo(zone_); |
| 1596 } | 1707 } |
| 1597 } // namespace wasm | 1708 } // namespace wasm |
| 1598 } // namespace internal | 1709 } // namespace internal |
| 1599 } // namespace v8 | 1710 } // namespace v8 |
| OLD | NEW |