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 (size_t i = 0; i < func_type->Arity(); i++) { |
| 477 sig.AddParam(TypeFrom(func_type->Parameter(static_cast<int>(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 (size_t i = 0; i < funcs->values()->length(); i++) { |
| 483 VariableProxy* func = |
| 484 funcs->values()->at(static_cast<int>(i))->AsVariableProxy(); |
| 485 DCHECK(func != nullptr); |
| 486 builder_->AddIndirectFunction(LookupOrInsertFunction(func->var())); |
| 487 } |
| 488 } |
| 489 |
| 490 struct FunctionTableIndices : public ZoneObject { |
| 491 uint16_t start_index; |
| 492 uint16_t signature_index; |
| 493 }; |
| 494 |
| 495 void InsertFunctionTable(Variable* v, uint16_t start_index, |
| 496 uint16_t signature_index) { |
| 497 FunctionTableIndices* container = new (zone()) FunctionTableIndices(); |
| 498 container->start_index = start_index; |
| 499 container->signature_index = signature_index; |
| 500 ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( |
| 501 v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); |
| 502 entry->value = container; |
| 503 } |
| 504 |
| 505 FunctionTableIndices* LookupFunctionTable(Variable* v) { |
| 506 ZoneHashMap::Entry* entry = |
| 507 function_tables_.Lookup(v, ComputePointerHash(v)); |
| 508 DCHECK(entry != nullptr); |
| 509 return reinterpret_cast<FunctionTableIndices*>(entry->value); |
| 510 } |
| 511 |
463 void VisitAssignment(Assignment* expr) { | 512 void VisitAssignment(Assignment* expr) { |
464 bool in_init = false; | 513 bool in_init = false; |
465 if (!in_function_) { | 514 if (!in_function_) { |
466 // TODO(bradnelson): Get rid of this. | 515 // TODO(bradnelson): Get rid of this. |
467 if (TypeOf(expr->value()) == kAstStmt) { | 516 if (TypeOf(expr->value()) == kAstStmt) { |
| 517 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| 518 if (funcs != nullptr && |
| 519 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { |
| 520 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 521 DCHECK(target != nullptr); |
| 522 AddFunctionTable(target, funcs); |
| 523 } |
468 return; | 524 return; |
469 } | 525 } |
470 in_init = true; | 526 in_init = true; |
471 LoadInitFunction(); | 527 LoadInitFunction(); |
472 } | 528 } |
473 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); | 529 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); |
474 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { | 530 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { |
475 VariableProxy* target_var = expr->target()->AsVariableProxy(); | 531 VariableProxy* target_var = expr->target()->AsVariableProxy(); |
476 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); | 532 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); |
477 if (target_var != nullptr && effective_value_var != nullptr && | 533 if (target_var != nullptr && effective_value_var != nullptr && |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 UNREACHABLE(); | 616 UNREACHABLE(); |
561 } | 617 } |
562 | 618 |
563 void VisitCall(Call* expr) { | 619 void VisitCall(Call* expr) { |
564 Call::CallType call_type = expr->GetCallType(isolate_); | 620 Call::CallType call_type = expr->GetCallType(isolate_); |
565 switch (call_type) { | 621 switch (call_type) { |
566 case Call::OTHER_CALL: { | 622 case Call::OTHER_CALL: { |
567 DCHECK(in_function_); | 623 DCHECK(in_function_); |
568 current_function_builder_->Emit(kExprCallFunction); | 624 current_function_builder_->Emit(kExprCallFunction); |
569 RECURSE(Visit(expr->expression())); | 625 RECURSE(Visit(expr->expression())); |
570 ZoneList<Expression*>* args = expr->arguments(); | 626 break; |
571 for (int i = 0; i < args->length(); ++i) { | 627 } |
572 Expression* arg = args->at(i); | 628 case Call::KEYED_PROPERTY_CALL: { |
573 RECURSE(Visit(arg)); | 629 DCHECK(in_function_); |
574 } | 630 Property* p = expr->expression()->AsProperty(); |
| 631 DCHECK(p != nullptr); |
| 632 VariableProxy* var = p->obj()->AsVariableProxy(); |
| 633 DCHECK(var != nullptr); |
| 634 FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
| 635 current_function_builder_->EmitWithU8(kExprCallIndirect, |
| 636 indices->signature_index); |
| 637 current_function_builder_->Emit(kExprI32Add); |
| 638 byte code[] = {WASM_I32(indices->start_index)}; |
| 639 current_function_builder_->EmitCode(code, sizeof(code)); |
| 640 RECURSE(Visit(p->key())); |
575 break; | 641 break; |
576 } | 642 } |
577 default: | 643 default: |
578 UNREACHABLE(); | 644 UNREACHABLE(); |
579 } | 645 } |
| 646 ZoneList<Expression*>* args = expr->arguments(); |
| 647 for (int i = 0; i < args->length(); ++i) { |
| 648 Expression* arg = args->at(i); |
| 649 RECURSE(Visit(arg)); |
| 650 } |
580 } | 651 } |
581 | 652 |
582 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } | 653 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } |
583 | 654 |
584 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } | 655 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } |
585 | 656 |
586 void VisitUnaryOperation(UnaryOperation* expr) { | 657 void VisitUnaryOperation(UnaryOperation* expr) { |
587 switch (expr->op()) { | 658 switch (expr->op()) { |
588 case Token::NOT: { | 659 case Token::NOT: { |
589 DCHECK(TypeOf(expr->expression()) == kAstI32); | 660 DCHECK(TypeOf(expr->expression()) == kAstI32); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 RECURSE(Visit(GetLeft(expr))); | 832 RECURSE(Visit(GetLeft(expr))); |
762 } else if (convertOperation == kAsIs) { | 833 } else if (convertOperation == kAsIs) { |
763 RECURSE(Visit(GetLeft(expr))); | 834 RECURSE(Visit(GetLeft(expr))); |
764 } else { | 835 } else { |
765 switch (expr->op()) { | 836 switch (expr->op()) { |
766 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); | 837 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); |
767 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); | 838 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); |
768 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); | 839 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); |
769 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); | 840 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); |
770 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); | 841 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); |
| 842 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); |
771 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); | 843 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); |
772 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); | 844 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); |
773 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); | 845 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); |
774 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); | 846 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); |
775 case Token::MOD: { | 847 case Token::MOD: { |
776 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); | 848 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); |
777 if (type == kInt32) { | 849 if (type == kInt32) { |
778 current_function_builder_->Emit(kExprI32RemS); | 850 current_function_builder_->Emit(kExprI32RemS); |
779 } else if (type == kUint32) { | 851 } else if (type == kUint32) { |
780 current_function_builder_->Emit(kExprI32RemU); | 852 current_function_builder_->Emit(kExprI32RemU); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 bool is_set_op_; | 1085 bool is_set_op_; |
1014 bool marking_exported; | 1086 bool marking_exported; |
1015 WasmModuleBuilder* builder_; | 1087 WasmModuleBuilder* builder_; |
1016 WasmFunctionBuilder* current_function_builder_; | 1088 WasmFunctionBuilder* current_function_builder_; |
1017 FunctionLiteral* literal_; | 1089 FunctionLiteral* literal_; |
1018 Isolate* isolate_; | 1090 Isolate* isolate_; |
1019 Zone* zone_; | 1091 Zone* zone_; |
1020 TypeCache const& cache_; | 1092 TypeCache const& cache_; |
1021 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1093 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
1022 int block_size_; | 1094 int block_size_; |
1023 uint16_t init_function_index; | 1095 uint16_t init_function_index_; |
| 1096 uint16_t next_table_index_; |
| 1097 ZoneHashMap function_tables_; |
1024 | 1098 |
1025 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1099 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1026 | 1100 |
1027 private: | 1101 private: |
1028 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1102 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
1029 }; | 1103 }; |
1030 | 1104 |
1031 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1105 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
1032 FunctionLiteral* literal) | 1106 FunctionLiteral* literal) |
1033 : isolate_(isolate), zone_(zone), literal_(literal) {} | 1107 : isolate_(isolate), zone_(zone), literal_(literal) {} |
1034 | 1108 |
1035 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1109 // 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. | 1110 // that zone in constructor may be thrown away once wasm module is written. |
1037 WasmModuleIndex* AsmWasmBuilder::Run() { | 1111 WasmModuleIndex* AsmWasmBuilder::Run() { |
1038 AsmWasmBuilderImpl impl(isolate_, zone_, literal_); | 1112 AsmWasmBuilderImpl impl(isolate_, zone_, literal_); |
1039 impl.Compile(); | 1113 impl.Compile(); |
1040 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1114 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
1041 return writer->WriteTo(zone_); | 1115 return writer->WriteTo(zone_); |
1042 } | 1116 } |
1043 } // namespace wasm | 1117 } // namespace wasm |
1044 } // namespace internal | 1118 } // namespace internal |
1045 } // namespace v8 | 1119 } // namespace v8 |
OLD | NEW |