| 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 #include "src/wasm/asm-wasm-builder.h" | 7 #include "src/wasm/asm-wasm-builder.h" |
| 8 #include "src/wasm/wasm-macro-gen.h" | 8 #include "src/wasm/wasm-macro-gen.h" |
| 9 #include "src/wasm/wasm-opcodes.h" | 9 #include "src/wasm/wasm-opcodes.h" |
| 10 | 10 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 is_set_op_(false), | 40 is_set_op_(false), |
| 41 marking_exported(false), | 41 marking_exported(false), |
| 42 builder_(new (zone) WasmModuleBuilder(zone)), | 42 builder_(new (zone) WasmModuleBuilder(zone)), |
| 43 current_function_builder_(nullptr), | 43 current_function_builder_(nullptr), |
| 44 literal_(literal), | 44 literal_(literal), |
| 45 isolate_(isolate), | 45 isolate_(isolate), |
| 46 zone_(zone), | 46 zone_(zone), |
| 47 cache_(TypeCache::Get()), | 47 cache_(TypeCache::Get()), |
| 48 breakable_blocks_(zone), | 48 breakable_blocks_(zone), |
| 49 block_size_(0), | 49 block_size_(0), |
| 50 init_function_index(0) { | 50 init_function_index_(0), |
| 51 next_table_index_(0), |
| 52 function_tables_(HashMap::PointersMatch, |
| 53 ZoneHashMap::kDefaultHashMapCapacity, |
| 54 ZoneAllocationPolicy(zone)) { |
| 51 InitializeAstVisitor(isolate); | 55 InitializeAstVisitor(isolate); |
| 52 } | 56 } |
| 53 | 57 |
| 54 void InitializeInitFunction() { | 58 void InitializeInitFunction() { |
| 55 unsigned char init[] = "__init__"; | 59 unsigned char init[] = "__init__"; |
| 56 init_function_index = builder_->AddFunction(); | 60 init_function_index_ = builder_->AddFunction(); |
| 57 current_function_builder_ = builder_->FunctionAt(init_function_index); | 61 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 58 current_function_builder_->SetName(init, 8); | 62 current_function_builder_->SetName(init, 8); |
| 59 current_function_builder_->ReturnType(kAstStmt); | 63 current_function_builder_->ReturnType(kAstStmt); |
| 60 current_function_builder_->Exported(1); | 64 current_function_builder_->Exported(1); |
| 61 current_function_builder_ = nullptr; | 65 current_function_builder_ = nullptr; |
| 62 } | 66 } |
| 63 | 67 |
| 64 void Compile() { | 68 void Compile() { |
| 65 InitializeInitFunction(); | 69 InitializeInitFunction(); |
| 66 RECURSE(VisitFunctionLiteral(literal_)); | 70 RECURSE(VisitFunctionLiteral(literal_)); |
| 67 } | 71 } |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 current_function_builder_->ReturnType(return_type); | 341 current_function_builder_->ReturnType(return_type); |
| 338 for (int i = 0; i < expr->parameter_count(); i++) { | 342 for (int i = 0; i < expr->parameter_count(); i++) { |
| 339 LocalType type = TypeFrom(func_type->Parameter(i)); | 343 LocalType type = TypeFrom(func_type->Parameter(i)); |
| 340 DCHECK(type != kAstStmt); | 344 DCHECK(type != kAstStmt); |
| 341 LookupOrInsertLocal(scope->parameter(i), type); | 345 LookupOrInsertLocal(scope->parameter(i), type); |
| 342 } | 346 } |
| 343 } else { | 347 } else { |
| 344 UNREACHABLE(); | 348 UNREACHABLE(); |
| 345 } | 349 } |
| 346 } | 350 } |
| 351 RECURSE(VisitStatements(expr->body())); |
| 347 RECURSE(VisitDeclarations(scope->declarations())); | 352 RECURSE(VisitDeclarations(scope->declarations())); |
| 348 RECURSE(VisitStatements(expr->body())); | |
| 349 } | 353 } |
| 350 | 354 |
| 351 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 355 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 352 UNREACHABLE(); | 356 UNREACHABLE(); |
| 353 } | 357 } |
| 354 | 358 |
| 355 void VisitConditional(Conditional* expr) { | 359 void VisitConditional(Conditional* expr) { |
| 356 DCHECK(in_function_); | 360 DCHECK(in_function_); |
| 357 current_function_builder_->Emit(kExprIfElse); | 361 current_function_builder_->Emit(kExprIfElse); |
| 358 RECURSE(Visit(expr->condition())); | 362 RECURSE(Visit(expr->condition())); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 builder_->FunctionAt(index)->Exported(1); | 448 builder_->FunctionAt(index)->Exported(1); |
| 445 builder_->FunctionAt(index) | 449 builder_->FunctionAt(index) |
| 446 ->SetName(raw_name->raw_data(), raw_name->length()); | 450 ->SetName(raw_name->raw_data(), raw_name->length()); |
| 447 } | 451 } |
| 448 } | 452 } |
| 449 } | 453 } |
| 450 | 454 |
| 451 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } | 455 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } |
| 452 | 456 |
| 453 void LoadInitFunction() { | 457 void LoadInitFunction() { |
| 454 current_function_builder_ = builder_->FunctionAt(init_function_index); | 458 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
| 455 in_function_ = true; | 459 in_function_ = true; |
| 456 } | 460 } |
| 457 | 461 |
| 458 void UnLoadInitFunction() { | 462 void UnLoadInitFunction() { |
| 459 in_function_ = false; | 463 in_function_ = false; |
| 460 current_function_builder_ = nullptr; | 464 current_function_builder_ = nullptr; |
| 461 } | 465 } |
| 462 | 466 |
| 467 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
| 468 Type::FunctionType* func_type = |
| 469 funcs->bounds().lower->AsArray()->Element()->AsFunction(); |
| 470 LocalType return_type = TypeFrom(func_type->Result()); |
| 471 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 472 func_type->Arity()); |
| 473 if (return_type != kAstStmt) { |
| 474 sig.AddReturn(static_cast<LocalType>(return_type)); |
| 475 } |
| 476 for (int i = 0; i < func_type->Arity(); i++) { |
| 477 sig.AddParam(TypeFrom(func_type->Parameter(i))); |
| 478 } |
| 479 uint16_t signature_index = builder_->AddSignature(sig.Build()); |
| 480 InsertFunctionTable(table->var(), next_table_index_, signature_index); |
| 481 next_table_index_ += funcs->values()->length(); |
| 482 for (int i = 0; i < funcs->values()->length(); i++) { |
| 483 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); |
| 484 DCHECK(func != nullptr); |
| 485 builder_->AddIndirectFunction(LookupOrInsertFunction(func->var())); |
| 486 } |
| 487 } |
| 488 |
| 489 struct FunctionTableIndices : public ZoneObject { |
| 490 uint32_t start_index; |
| 491 uint16_t signature_index; |
| 492 }; |
| 493 |
| 494 void InsertFunctionTable(Variable* v, uint32_t start_index, |
| 495 uint16_t signature_index) { |
| 496 FunctionTableIndices* container = new (zone()) FunctionTableIndices(); |
| 497 container->start_index = start_index; |
| 498 container->signature_index = signature_index; |
| 499 ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( |
| 500 v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); |
| 501 entry->value = container; |
| 502 } |
| 503 |
| 504 FunctionTableIndices* LookupFunctionTable(Variable* v) { |
| 505 ZoneHashMap::Entry* entry = |
| 506 function_tables_.Lookup(v, ComputePointerHash(v)); |
| 507 DCHECK(entry != nullptr); |
| 508 return reinterpret_cast<FunctionTableIndices*>(entry->value); |
| 509 } |
| 510 |
| 463 void VisitAssignment(Assignment* expr) { | 511 void VisitAssignment(Assignment* expr) { |
| 464 bool in_init = false; | 512 bool in_init = false; |
| 465 if (!in_function_) { | 513 if (!in_function_) { |
| 466 // TODO(bradnelson): Get rid of this. | 514 // TODO(bradnelson): Get rid of this. |
| 467 if (TypeOf(expr->value()) == kAstStmt) { | 515 if (TypeOf(expr->value()) == kAstStmt) { |
| 516 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| 517 if (funcs != nullptr && |
| 518 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { |
| 519 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 520 DCHECK(target != nullptr); |
| 521 AddFunctionTable(target, funcs); |
| 522 } |
| 468 return; | 523 return; |
| 469 } | 524 } |
| 470 in_init = true; | 525 in_init = true; |
| 471 LoadInitFunction(); | 526 LoadInitFunction(); |
| 472 } | 527 } |
| 473 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); | 528 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); |
| 474 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { | 529 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { |
| 475 VariableProxy* target_var = expr->target()->AsVariableProxy(); | 530 VariableProxy* target_var = expr->target()->AsVariableProxy(); |
| 476 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); | 531 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); |
| 477 if (target_var != nullptr && effective_value_var != nullptr && | 532 if (target_var != nullptr && effective_value_var != nullptr && |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 UNREACHABLE(); | 615 UNREACHABLE(); |
| 561 } | 616 } |
| 562 | 617 |
| 563 void VisitCall(Call* expr) { | 618 void VisitCall(Call* expr) { |
| 564 Call::CallType call_type = expr->GetCallType(isolate_); | 619 Call::CallType call_type = expr->GetCallType(isolate_); |
| 565 switch (call_type) { | 620 switch (call_type) { |
| 566 case Call::OTHER_CALL: { | 621 case Call::OTHER_CALL: { |
| 567 DCHECK(in_function_); | 622 DCHECK(in_function_); |
| 568 current_function_builder_->Emit(kExprCallFunction); | 623 current_function_builder_->Emit(kExprCallFunction); |
| 569 RECURSE(Visit(expr->expression())); | 624 RECURSE(Visit(expr->expression())); |
| 570 ZoneList<Expression*>* args = expr->arguments(); | 625 break; |
| 571 for (int i = 0; i < args->length(); ++i) { | 626 } |
| 572 Expression* arg = args->at(i); | 627 case Call::KEYED_PROPERTY_CALL: { |
| 573 RECURSE(Visit(arg)); | 628 DCHECK(in_function_); |
| 574 } | 629 Property* p = expr->expression()->AsProperty(); |
| 630 DCHECK(p != nullptr); |
| 631 VariableProxy* var = p->obj()->AsVariableProxy(); |
| 632 DCHECK(var != nullptr); |
| 633 FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
| 634 current_function_builder_->EmitWithU8(kExprCallIndirect, |
| 635 indices->signature_index); |
| 636 current_function_builder_->Emit(kExprI32Add); |
| 637 byte code[] = {WASM_I32(indices->start_index)}; |
| 638 current_function_builder_->EmitCode(code, sizeof(code)); |
| 639 RECURSE(Visit(p->key())); |
| 575 break; | 640 break; |
| 576 } | 641 } |
| 577 default: | 642 default: |
| 578 UNREACHABLE(); | 643 UNREACHABLE(); |
| 579 } | 644 } |
| 645 ZoneList<Expression*>* args = expr->arguments(); |
| 646 for (int i = 0; i < args->length(); ++i) { |
| 647 Expression* arg = args->at(i); |
| 648 RECURSE(Visit(arg)); |
| 649 } |
| 580 } | 650 } |
| 581 | 651 |
| 582 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } | 652 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } |
| 583 | 653 |
| 584 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } | 654 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } |
| 585 | 655 |
| 586 void VisitUnaryOperation(UnaryOperation* expr) { | 656 void VisitUnaryOperation(UnaryOperation* expr) { |
| 587 switch (expr->op()) { | 657 switch (expr->op()) { |
| 588 case Token::NOT: { | 658 case Token::NOT: { |
| 589 DCHECK(TypeOf(expr->expression()) == kAstI32); | 659 DCHECK(TypeOf(expr->expression()) == kAstI32); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 RECURSE(Visit(GetLeft(expr))); | 831 RECURSE(Visit(GetLeft(expr))); |
| 762 } else if (convertOperation == kAsIs) { | 832 } else if (convertOperation == kAsIs) { |
| 763 RECURSE(Visit(GetLeft(expr))); | 833 RECURSE(Visit(GetLeft(expr))); |
| 764 } else { | 834 } else { |
| 765 switch (expr->op()) { | 835 switch (expr->op()) { |
| 766 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); | 836 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); |
| 767 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); | 837 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); |
| 768 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); | 838 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); |
| 769 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); | 839 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); |
| 770 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); | 840 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); |
| 841 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); |
| 771 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); | 842 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); |
| 772 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); | 843 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); |
| 773 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); | 844 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); |
| 774 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); | 845 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); |
| 775 case Token::MOD: { | 846 case Token::MOD: { |
| 776 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); | 847 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); |
| 777 if (type == kInt32) { | 848 if (type == kInt32) { |
| 778 current_function_builder_->Emit(kExprI32RemS); | 849 current_function_builder_->Emit(kExprI32RemS); |
| 779 } else if (type == kUint32) { | 850 } else if (type == kUint32) { |
| 780 current_function_builder_->Emit(kExprI32RemU); | 851 current_function_builder_->Emit(kExprI32RemU); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 bool is_set_op_; | 1084 bool is_set_op_; |
| 1014 bool marking_exported; | 1085 bool marking_exported; |
| 1015 WasmModuleBuilder* builder_; | 1086 WasmModuleBuilder* builder_; |
| 1016 WasmFunctionBuilder* current_function_builder_; | 1087 WasmFunctionBuilder* current_function_builder_; |
| 1017 FunctionLiteral* literal_; | 1088 FunctionLiteral* literal_; |
| 1018 Isolate* isolate_; | 1089 Isolate* isolate_; |
| 1019 Zone* zone_; | 1090 Zone* zone_; |
| 1020 TypeCache const& cache_; | 1091 TypeCache const& cache_; |
| 1021 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1092 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
| 1022 int block_size_; | 1093 int block_size_; |
| 1023 uint16_t init_function_index; | 1094 uint16_t init_function_index_; |
| 1095 uint32_t next_table_index_; |
| 1096 ZoneHashMap function_tables_; |
| 1024 | 1097 |
| 1025 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1098 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 1026 | 1099 |
| 1027 private: | 1100 private: |
| 1028 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1101 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
| 1029 }; | 1102 }; |
| 1030 | 1103 |
| 1031 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1104 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
| 1032 FunctionLiteral* literal) | 1105 FunctionLiteral* literal) |
| 1033 : isolate_(isolate), zone_(zone), literal_(literal) {} | 1106 : isolate_(isolate), zone_(zone), literal_(literal) {} |
| 1034 | 1107 |
| 1035 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1108 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
| 1036 // that zone in constructor may be thrown away once wasm module is written. | 1109 // that zone in constructor may be thrown away once wasm module is written. |
| 1037 WasmModuleIndex* AsmWasmBuilder::Run() { | 1110 WasmModuleIndex* AsmWasmBuilder::Run() { |
| 1038 AsmWasmBuilderImpl impl(isolate_, zone_, literal_); | 1111 AsmWasmBuilderImpl impl(isolate_, zone_, literal_); |
| 1039 impl.Compile(); | 1112 impl.Compile(); |
| 1040 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1113 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
| 1041 return writer->WriteTo(zone_); | 1114 return writer->WriteTo(zone_); |
| 1042 } | 1115 } |
| 1043 } // namespace wasm | 1116 } // namespace wasm |
| 1044 } // namespace internal | 1117 } // namespace internal |
| 1045 } // namespace v8 | 1118 } // namespace v8 |
| OLD | NEW |