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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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), | 51 next_table_index_(0), |
52 function_tables_(HashMap::PointersMatch, | 52 function_tables_(HashMap::PointersMatch, |
53 ZoneHashMap::kDefaultHashMapCapacity, | 53 ZoneHashMap::kDefaultHashMapCapacity, |
54 ZoneAllocationPolicy(zone)) { | 54 ZoneAllocationPolicy(zone)), |
| 55 imported_function_table_(this) { |
55 InitializeAstVisitor(isolate); | 56 InitializeAstVisitor(isolate); |
56 } | 57 } |
57 | 58 |
58 void InitializeInitFunction() { | 59 void InitializeInitFunction() { |
59 unsigned char init[] = "__init__"; | 60 unsigned char init[] = "__init__"; |
60 init_function_index_ = builder_->AddFunction(); | 61 init_function_index_ = builder_->AddFunction(); |
61 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 62 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
62 current_function_builder_->SetName(init, 8); | 63 current_function_builder_->SetName(init, 8); |
63 current_function_builder_->ReturnType(kAstStmt); | 64 current_function_builder_->ReturnType(kAstStmt); |
64 current_function_builder_->Exported(1); | 65 current_function_builder_->Exported(1); |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 DCHECK(in_function_); | 361 DCHECK(in_function_); |
361 current_function_builder_->Emit(kExprIfElse); | 362 current_function_builder_->Emit(kExprIfElse); |
362 RECURSE(Visit(expr->condition())); | 363 RECURSE(Visit(expr->condition())); |
363 RECURSE(Visit(expr->then_expression())); | 364 RECURSE(Visit(expr->then_expression())); |
364 RECURSE(Visit(expr->else_expression())); | 365 RECURSE(Visit(expr->else_expression())); |
365 } | 366 } |
366 | 367 |
367 void VisitVariableProxy(VariableProxy* expr) { | 368 void VisitVariableProxy(VariableProxy* expr) { |
368 if (in_function_) { | 369 if (in_function_) { |
369 Variable* var = expr->var(); | 370 Variable* var = expr->var(); |
370 if (var->is_function()) { | 371 if (is_set_op_) { |
371 DCHECK(!is_set_op_); | 372 if (var->IsContextSlot()) { |
372 std::vector<uint8_t> index = | 373 current_function_builder_->Emit(kExprStoreGlobal); |
373 UnsignedLEB128From(LookupOrInsertFunction(var)); | 374 } else { |
374 current_function_builder_->EmitCode( | 375 current_function_builder_->Emit(kExprSetLocal); |
375 &index[0], static_cast<uint32_t>(index.size())); | 376 } |
| 377 is_set_op_ = false; |
376 } else { | 378 } else { |
377 if (is_set_op_) { | 379 if (var->IsContextSlot()) { |
378 if (var->IsContextSlot()) { | 380 current_function_builder_->Emit(kExprLoadGlobal); |
379 current_function_builder_->Emit(kExprStoreGlobal); | |
380 } else { | |
381 current_function_builder_->Emit(kExprSetLocal); | |
382 } | |
383 is_set_op_ = false; | |
384 } else { | 381 } else { |
385 if (var->IsContextSlot()) { | 382 current_function_builder_->Emit(kExprGetLocal); |
386 current_function_builder_->Emit(kExprLoadGlobal); | |
387 } else { | |
388 current_function_builder_->Emit(kExprGetLocal); | |
389 } | |
390 } | 383 } |
391 LocalType var_type = TypeOf(expr); | 384 } |
392 DCHECK(var_type != kAstStmt); | 385 LocalType var_type = TypeOf(expr); |
393 if (var->IsContextSlot()) { | 386 DCHECK(var_type != kAstStmt); |
394 AddLeb128(LookupOrInsertGlobal(var, var_type), false); | 387 if (var->IsContextSlot()) { |
395 } else { | 388 AddLeb128(LookupOrInsertGlobal(var, var_type), false); |
396 AddLeb128(LookupOrInsertLocal(var, var_type), true); | 389 } else { |
397 } | 390 AddLeb128(LookupOrInsertLocal(var, var_type), true); |
398 } | 391 } |
399 } | 392 } |
400 } | 393 } |
401 | 394 |
402 void VisitLiteral(Literal* expr) { | 395 void VisitLiteral(Literal* expr) { |
403 if (in_function_) { | 396 if (in_function_) { |
404 if (expr->raw_value()->IsNumber()) { | 397 if (expr->raw_value()->IsNumber()) { |
405 LocalType type = TypeOf(expr); | 398 LocalType type = TypeOf(expr); |
406 switch (type) { | 399 switch (type) { |
407 case kAstI32: { | 400 case kAstI32: { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 entry->value = container; | 494 entry->value = container; |
502 } | 495 } |
503 | 496 |
504 FunctionTableIndices* LookupFunctionTable(Variable* v) { | 497 FunctionTableIndices* LookupFunctionTable(Variable* v) { |
505 ZoneHashMap::Entry* entry = | 498 ZoneHashMap::Entry* entry = |
506 function_tables_.Lookup(v, ComputePointerHash(v)); | 499 function_tables_.Lookup(v, ComputePointerHash(v)); |
507 DCHECK(entry != nullptr); | 500 DCHECK(entry != nullptr); |
508 return reinterpret_cast<FunctionTableIndices*>(entry->value); | 501 return reinterpret_cast<FunctionTableIndices*>(entry->value); |
509 } | 502 } |
510 | 503 |
| 504 class ImportedFunctionTable { |
| 505 private: |
| 506 class ImportedFunctionIndices : public ZoneObject { |
| 507 public: |
| 508 const unsigned char* name_; |
| 509 int name_length_; |
| 510 WasmModuleBuilder::SignatureMap signature_to_index_; |
| 511 |
| 512 ImportedFunctionIndices(const unsigned char* name, int name_length, |
| 513 Zone* zone) |
| 514 : name_(name), name_length_(name_length), signature_to_index_(zone) {} |
| 515 }; |
| 516 ZoneHashMap table_; |
| 517 AsmWasmBuilderImpl* builder_; |
| 518 |
| 519 public: |
| 520 explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) |
| 521 : table_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, |
| 522 ZoneAllocationPolicy(builder->zone())), |
| 523 builder_(builder) {} |
| 524 |
| 525 void AddImport(Variable* v, const unsigned char* name, int name_length) { |
| 526 ImportedFunctionIndices* indices = new (builder_->zone()) |
| 527 ImportedFunctionIndices(name, name_length, builder_->zone()); |
| 528 ZoneHashMap::Entry* entry = table_.LookupOrInsert( |
| 529 v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); |
| 530 entry->value = indices; |
| 531 } |
| 532 |
| 533 uint16_t GetFunctionIndex(Variable* v, FunctionSig* sig) { |
| 534 ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v)); |
| 535 DCHECK(entry != nullptr); |
| 536 ImportedFunctionIndices* indices = |
| 537 reinterpret_cast<ImportedFunctionIndices*>(entry->value); |
| 538 WasmModuleBuilder::SignatureMap::iterator pos = |
| 539 indices->signature_to_index_.find(sig); |
| 540 if (pos != indices->signature_to_index_.end()) { |
| 541 return pos->second; |
| 542 } else { |
| 543 uint16_t index = builder_->builder_->AddFunction(); |
| 544 indices->signature_to_index_[sig] = index; |
| 545 WasmFunctionBuilder* function = builder_->builder_->FunctionAt(index); |
| 546 function->External(1); |
| 547 function->SetName(indices->name_, indices->name_length_); |
| 548 if (sig->return_count() > 0) { |
| 549 function->ReturnType(sig->GetReturn()); |
| 550 } |
| 551 for (size_t i = 0; i < sig->parameter_count(); i++) { |
| 552 function->AddParam(sig->GetParam(i)); |
| 553 } |
| 554 return index; |
| 555 } |
| 556 } |
| 557 }; |
| 558 |
511 void VisitAssignment(Assignment* expr) { | 559 void VisitAssignment(Assignment* expr) { |
512 bool in_init = false; | 560 bool in_init = false; |
513 if (!in_function_) { | 561 if (!in_function_) { |
514 // TODO(bradnelson): Get rid of this. | 562 // TODO(bradnelson): Get rid of this. |
515 if (TypeOf(expr->value()) == kAstStmt) { | 563 if (TypeOf(expr->value()) == kAstStmt) { |
| 564 Property* prop = expr->value()->AsProperty(); |
| 565 if (prop != nullptr) { |
| 566 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
| 567 if (vp != nullptr && vp->var()->IsParameter() && |
| 568 vp->var()->index() == 1) { |
| 569 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 570 if (target->bounds().lower->Is(Type::Function())) { |
| 571 const AstRawString* name = |
| 572 prop->key()->AsLiteral()->AsRawPropertyName(); |
| 573 imported_function_table_.AddImport( |
| 574 target->var(), name->raw_data(), name->length()); |
| 575 } |
| 576 } |
| 577 } |
516 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 578 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
517 if (funcs != nullptr && | 579 if (funcs != nullptr && |
518 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { | 580 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { |
519 VariableProxy* target = expr->target()->AsVariableProxy(); | 581 VariableProxy* target = expr->target()->AsVariableProxy(); |
520 DCHECK(target != nullptr); | 582 DCHECK(target != nullptr); |
521 AddFunctionTable(target, funcs); | 583 AddFunctionTable(target, funcs); |
522 } | 584 } |
523 return; | 585 return; |
524 } | 586 } |
525 in_init = true; | 587 in_init = true; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 return; | 675 return; |
614 } | 676 } |
615 UNREACHABLE(); | 677 UNREACHABLE(); |
616 } | 678 } |
617 | 679 |
618 void VisitCall(Call* expr) { | 680 void VisitCall(Call* expr) { |
619 Call::CallType call_type = expr->GetCallType(isolate_); | 681 Call::CallType call_type = expr->GetCallType(isolate_); |
620 switch (call_type) { | 682 switch (call_type) { |
621 case Call::OTHER_CALL: { | 683 case Call::OTHER_CALL: { |
622 DCHECK(in_function_); | 684 DCHECK(in_function_); |
| 685 uint16_t index; |
| 686 VariableProxy* vp = expr->expression()->AsVariableProxy(); |
| 687 if (vp != nullptr && |
| 688 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { |
| 689 LocalType return_type = TypeOf(expr); |
| 690 ZoneList<Expression*>* args = expr->arguments(); |
| 691 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 692 args->length()); |
| 693 if (return_type != kAstStmt) { |
| 694 sig.AddReturn(return_type); |
| 695 } |
| 696 for (int i = 0; i < args->length(); i++) { |
| 697 sig.AddParam(TypeOf(args->at(i))); |
| 698 } |
| 699 index = |
| 700 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); |
| 701 } else { |
| 702 index = LookupOrInsertFunction(vp->var()); |
| 703 } |
623 current_function_builder_->Emit(kExprCallFunction); | 704 current_function_builder_->Emit(kExprCallFunction); |
624 RECURSE(Visit(expr->expression())); | 705 std::vector<uint8_t> index_arr = UnsignedLEB128From(index); |
| 706 current_function_builder_->EmitCode( |
| 707 &index_arr[0], static_cast<uint32_t>(index_arr.size())); |
625 break; | 708 break; |
626 } | 709 } |
627 case Call::KEYED_PROPERTY_CALL: { | 710 case Call::KEYED_PROPERTY_CALL: { |
628 DCHECK(in_function_); | 711 DCHECK(in_function_); |
629 Property* p = expr->expression()->AsProperty(); | 712 Property* p = expr->expression()->AsProperty(); |
630 DCHECK(p != nullptr); | 713 DCHECK(p != nullptr); |
631 VariableProxy* var = p->obj()->AsVariableProxy(); | 714 VariableProxy* var = p->obj()->AsVariableProxy(); |
632 DCHECK(var != nullptr); | 715 DCHECK(var != nullptr); |
633 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 716 FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
634 current_function_builder_->EmitWithU8(kExprCallIndirect, | 717 current_function_builder_->EmitWithU8(kExprCallIndirect, |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1087 WasmFunctionBuilder* current_function_builder_; | 1170 WasmFunctionBuilder* current_function_builder_; |
1088 FunctionLiteral* literal_; | 1171 FunctionLiteral* literal_; |
1089 Isolate* isolate_; | 1172 Isolate* isolate_; |
1090 Zone* zone_; | 1173 Zone* zone_; |
1091 TypeCache const& cache_; | 1174 TypeCache const& cache_; |
1092 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1175 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
1093 int block_size_; | 1176 int block_size_; |
1094 uint16_t init_function_index_; | 1177 uint16_t init_function_index_; |
1095 uint32_t next_table_index_; | 1178 uint32_t next_table_index_; |
1096 ZoneHashMap function_tables_; | 1179 ZoneHashMap function_tables_; |
| 1180 ImportedFunctionTable imported_function_table_; |
1097 | 1181 |
1098 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1182 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1099 | 1183 |
1100 private: | 1184 private: |
1101 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1185 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
1102 }; | 1186 }; |
1103 | 1187 |
1104 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1188 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
1105 FunctionLiteral* literal) | 1189 FunctionLiteral* literal) |
1106 : isolate_(isolate), zone_(zone), literal_(literal) {} | 1190 : isolate_(isolate), zone_(zone), literal_(literal) {} |
1107 | 1191 |
1108 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1192 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
1109 // that zone in constructor may be thrown away once wasm module is written. | 1193 // that zone in constructor may be thrown away once wasm module is written. |
1110 WasmModuleIndex* AsmWasmBuilder::Run() { | 1194 WasmModuleIndex* AsmWasmBuilder::Run() { |
1111 AsmWasmBuilderImpl impl(isolate_, zone_, literal_); | 1195 AsmWasmBuilderImpl impl(isolate_, zone_, literal_); |
1112 impl.Compile(); | 1196 impl.Compile(); |
1113 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1197 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
1114 return writer->WriteTo(zone_); | 1198 return writer->WriteTo(zone_); |
1115 } | 1199 } |
1116 } // namespace wasm | 1200 } // namespace wasm |
1117 } // namespace internal | 1201 } // namespace internal |
1118 } // namespace v8 | 1202 } // namespace v8 |
OLD | NEW |