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 |
| 11 #include <math.h> | 11 #include <math.h> |
| 12 | 12 |
| 13 #include "src/wasm/asm-wasm-builder.h" | 13 #include "src/wasm/asm-wasm-builder.h" |
| 14 #include "src/wasm/switch-logic.h" | |
| 14 #include "src/wasm/wasm-macro-gen.h" | 15 #include "src/wasm/wasm-macro-gen.h" |
| 15 #include "src/wasm/wasm-opcodes.h" | 16 #include "src/wasm/wasm-opcodes.h" |
| 16 | 17 |
| 17 #include "src/ast/ast.h" | 18 #include "src/ast/ast.h" |
| 18 #include "src/ast/scopes.h" | 19 #include "src/ast/scopes.h" |
| 19 #include "src/codegen.h" | 20 #include "src/codegen.h" |
| 20 #include "src/type-cache.h" | 21 #include "src/type-cache.h" |
| 21 | 22 |
| 22 namespace v8 { | 23 namespace v8 { |
| 23 namespace internal { | 24 namespace internal { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 local_variables_.Clear(); | 93 local_variables_.Clear(); |
| 93 } | 94 } |
| 94 | 95 |
| 95 void VisitImportDeclaration(ImportDeclaration* decl) {} | 96 void VisitImportDeclaration(ImportDeclaration* decl) {} |
| 96 | 97 |
| 97 void VisitExportDeclaration(ExportDeclaration* decl) {} | 98 void VisitExportDeclaration(ExportDeclaration* decl) {} |
| 98 | 99 |
| 99 void VisitStatements(ZoneList<Statement*>* stmts) { | 100 void VisitStatements(ZoneList<Statement*>* stmts) { |
| 100 for (int i = 0; i < stmts->length(); ++i) { | 101 for (int i = 0; i < stmts->length(); ++i) { |
| 101 Statement* stmt = stmts->at(i); | 102 Statement* stmt = stmts->at(i); |
| 103 ExpressionStatement* e = stmt->AsExpressionStatement(); | |
| 104 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { | |
| 105 block_size_--; | |
| 106 continue; | |
| 107 } | |
| 102 RECURSE(Visit(stmt)); | 108 RECURSE(Visit(stmt)); |
| 103 if (stmt->IsJump()) break; | 109 if (stmt->IsJump()) break; |
| 104 } | 110 } |
| 105 } | 111 } |
| 106 | 112 |
| 107 void VisitBlock(Block* stmt) { | 113 void VisitBlock(Block* stmt) { |
| 108 if (stmt->statements()->length() == 1) { | 114 if (stmt->statements()->length() == 1) { |
| 109 ExpressionStatement* expr = | 115 ExpressionStatement* expr = |
| 110 stmt->statements()->at(0)->AsExpressionStatement(); | 116 stmt->statements()->at(0)->AsExpressionStatement(); |
| 111 if (expr != nullptr) { | 117 if (expr != nullptr) { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 marking_exported = true; | 234 marking_exported = true; |
| 229 } | 235 } |
| 230 RECURSE(Visit(stmt->expression())); | 236 RECURSE(Visit(stmt->expression())); |
| 231 if (!in_function_) { | 237 if (!in_function_) { |
| 232 marking_exported = false; | 238 marking_exported = false; |
| 233 } | 239 } |
| 234 } | 240 } |
| 235 | 241 |
| 236 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } | 242 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } |
| 237 | 243 |
| 238 void SetLocalTo(uint16_t index, int value) { | 244 void GenerateCaseComparisonCode(int value, WasmOpcode op, |
| 239 current_function_builder_->Emit(kExprSetLocal); | 245 VariableProxy* tag) { |
| 240 AddLeb128(index, true); | 246 current_function_builder_->Emit(kExprIfElse); |
| 241 // TODO(bradnelson): variable size | 247 current_function_builder_->Emit(op); |
| 248 VisitVariableProxy(tag); | |
| 242 byte code[] = {WASM_I32V(value)}; | 249 byte code[] = {WASM_I32V(value)}; |
| 243 current_function_builder_->EmitCode(code, sizeof(code)); | 250 current_function_builder_->EmitCode(code, sizeof(code)); |
| 244 block_size_++; | |
| 245 } | 251 } |
| 246 | 252 |
| 247 void CompileCase(CaseClause* clause, uint16_t fall_through, | 253 void HandleCase(CaseNode* node, |
| 248 VariableProxy* tag) { | 254 const ZoneMap<int, unsigned int>& case_to_block, |
| 249 Literal* label = clause->label()->AsLiteral(); | 255 VariableProxy* tag, int default_block) { |
| 250 DCHECK_NOT_NULL(label); | 256 if (node->left != nullptr) { |
| 251 block_size_++; | 257 GenerateCaseComparisonCode(node->begin, kExprI32LtS, tag); |
| 252 current_function_builder_->Emit(kExprIf); | 258 HandleCase(node->left, case_to_block, tag, default_block); |
| 253 current_function_builder_->Emit(kExprI32Ior); | 259 } |
| 254 current_function_builder_->Emit(kExprI32Eq); | 260 if (node->right != nullptr) { |
| 255 VisitVariableProxy(tag); | 261 GenerateCaseComparisonCode(node->end, kExprI32GtS, tag); |
| 256 VisitLiteral(label); | 262 HandleCase(node->right, case_to_block, tag, default_block); |
| 257 current_function_builder_->Emit(kExprGetLocal); | 263 } |
| 258 AddLeb128(fall_through, true); | 264 if (node->begin == node->end) { |
| 259 BlockVisitor visitor(this, nullptr, kExprBlock, false, 0); | 265 current_function_builder_->Emit(kExprIf); |
| 260 SetLocalTo(fall_through, 1); | 266 current_function_builder_->Emit(kExprI32Eq); |
| 261 ZoneList<Statement*>* stmts = clause->statements(); | 267 VisitVariableProxy(tag); |
| 262 block_size_ += stmts->length(); | 268 byte code[] = {WASM_I32V(node->begin)}; |
| 263 RECURSE(VisitStatements(stmts)); | 269 current_function_builder_->EmitCode(code, sizeof(code)); |
| 270 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); | |
| 274 } else { | |
| 275 current_function_builder_->Emit(kExprBrTable); | |
| 276 std::vector<uint8_t> count = | |
| 277 UnsignedLEB128From(node->end - node->begin + 1); | |
| 278 current_function_builder_->EmitCode(&count[0], | |
| 279 static_cast<uint32_t>(count.size())); | |
| 280 for (int v = node->begin; v <= node->end; v++) { | |
| 281 if (case_to_block.find(v) != case_to_block.end()) { | |
| 282 byte break_code[] = {BR_TARGET(case_to_block.at(v))}; | |
| 283 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | |
| 284 } else { | |
| 285 byte break_code[] = {BR_TARGET(default_block)}; | |
| 286 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | |
| 287 } | |
| 288 } | |
| 289 byte break_code[] = {BR_TARGET(default_block)}; | |
| 290 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | |
| 291 if (node->begin != 0) { | |
|
bradn
2016/04/07 23:46:59
Can you add a TODO / comment that this is required
aseemgarg
2016/04/11 20:59:19
problem fixed now
aseemgarg
2016/04/11 21:00:32
Problem wasn't fixed. So, put the if back in with
| |
| 292 current_function_builder_->Emit(kExprI32Sub); | |
| 293 VisitVariableProxy(tag); | |
| 294 byte code[] = {WASM_I32V(node->begin)}; | |
| 295 current_function_builder_->EmitCode(code, sizeof(code)); | |
| 296 } else { | |
| 297 VisitVariableProxy(tag); | |
| 298 } | |
| 299 } | |
| 264 } | 300 } |
| 265 | 301 |
| 266 void VisitSwitchStatement(SwitchStatement* stmt) { | 302 void VisitSwitchStatement(SwitchStatement* stmt) { |
| 267 VariableProxy* tag = stmt->tag()->AsVariableProxy(); | 303 VariableProxy* tag = stmt->tag()->AsVariableProxy(); |
| 268 DCHECK_NOT_NULL(tag); | 304 DCHECK_NOT_NULL(tag); |
| 305 ZoneList<CaseClause*>* clauses = stmt->cases(); | |
| 306 int case_count = clauses->length(); | |
| 307 if (case_count == 0) { | |
| 308 block_size_--; | |
| 309 return; | |
| 310 } | |
| 269 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false, | 311 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false, |
| 270 0); | 312 1); |
| 271 uint16_t fall_through = current_function_builder_->AddLocal(kAstI32); | 313 ZoneVector<BlockVisitor*> blocks(zone_); |
| 272 SetLocalTo(fall_through, 0); | 314 ZoneVector<int32_t> cases(zone_); |
| 273 | 315 ZoneMap<int, unsigned int> case_to_block(zone_); |
| 274 ZoneList<CaseClause*>* clauses = stmt->cases(); | 316 bool has_default = false; |
| 275 for (int i = 0; i < clauses->length(); ++i) { | 317 for (int i = case_count - 1; i >= 0; i--) { |
| 276 CaseClause* clause = clauses->at(i); | 318 CaseClause* clause = clauses->at(i); |
| 319 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false, | |
| 320 clause->statements()->length() + 1)); | |
| 277 if (!clause->is_default()) { | 321 if (!clause->is_default()) { |
| 278 CompileCase(clause, fall_through, tag); | 322 Literal* label = clause->label()->AsLiteral(); |
| 323 Handle<Object> value = label->value(); | |
| 324 DCHECK(value->IsNumber() && | |
| 325 label->bounds().upper->Is(cache_.kAsmSigned)); | |
| 326 int32_t label_value; | |
| 327 if (!value->ToInt32(&label_value)) { | |
| 328 UNREACHABLE(); | |
| 329 } | |
| 330 case_to_block[label_value] = i; | |
| 331 cases.push_back(label_value); | |
| 279 } else { | 332 } else { |
| 280 ZoneList<Statement*>* stmts = clause->statements(); | 333 DCHECK_EQ(i, case_count - 1); |
| 281 block_size_ += stmts->length(); | 334 has_default = true; |
| 282 RECURSE(VisitStatements(stmts)); | |
| 283 } | 335 } |
| 284 } | 336 } |
| 337 if (!has_default || case_count > 1) { | |
| 338 int default_block = has_default ? case_count - 1 : case_count; | |
| 339 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false, 1); | |
| 340 CaseNode* root = OrderCases(&cases, zone_); | |
| 341 HandleCase(root, case_to_block, tag, default_block); | |
| 342 if (root->left != nullptr || root->right != nullptr || | |
| 343 root->begin == root->end) { | |
| 344 block_size_++; | |
| 345 current_function_builder_->EmitWithVarInt(kExprBr, default_block); | |
| 346 current_function_builder_->Emit(kExprNop); | |
| 347 } | |
| 348 } else { | |
| 349 block_size_ = clauses->at(0)->statements()->length(); | |
| 350 } | |
| 351 for (int i = 0; i < case_count; i++) { | |
| 352 CaseClause* clause = clauses->at(i); | |
| 353 RECURSE(VisitStatements(clause->statements())); | |
| 354 BlockVisitor* v = blocks.at(case_count - i - 1); | |
| 355 blocks.pop_back(); | |
| 356 delete v; | |
| 357 } | |
| 285 } | 358 } |
| 286 | 359 |
| 287 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 360 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |
| 288 | 361 |
| 289 void VisitDoWhileStatement(DoWhileStatement* stmt) { | 362 void VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 290 DCHECK(in_function_); | 363 DCHECK(in_function_); |
| 291 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 364 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, |
| 292 2); | 365 2); |
| 293 RECURSE(Visit(stmt->body())); | 366 RECURSE(Visit(stmt->body())); |
| 294 current_function_builder_->Emit(kExprIf); | 367 current_function_builder_->Emit(kExprIf); |
| (...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1533 // that zone in constructor may be thrown away once wasm module is written. | 1606 // that zone in constructor may be thrown away once wasm module is written. |
| 1534 WasmModuleIndex* AsmWasmBuilder::Run() { | 1607 WasmModuleIndex* AsmWasmBuilder::Run() { |
| 1535 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); | 1608 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); |
| 1536 impl.Compile(); | 1609 impl.Compile(); |
| 1537 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1610 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
| 1538 return writer->WriteTo(zone_); | 1611 return writer->WriteTo(zone_); |
| 1539 } | 1612 } |
| 1540 } // namespace wasm | 1613 } // namespace wasm |
| 1541 } // namespace internal | 1614 } // namespace internal |
| 1542 } // namespace v8 | 1615 } // namespace v8 |
| OLD | NEW |