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 |
11 #include "src/ast/ast.h" | 11 #include "src/ast/ast.h" |
12 #include "src/ast/scopes.h" | 12 #include "src/ast/scopes.h" |
13 #include "src/codegen.h" | 13 #include "src/codegen.h" |
14 #include "src/type-cache.h" | 14 #include "src/type-cache.h" |
15 | 15 |
16 namespace v8 { | 16 namespace v8 { |
17 namespace internal { | 17 namespace internal { |
18 namespace wasm { | 18 namespace wasm { |
19 | 19 |
20 #define RECURSE(call) \ | 20 #define RECURSE(call) \ |
21 do { \ | 21 do { \ |
22 DCHECK(!HasStackOverflow()); \ | 22 DCHECK(!HasStackOverflow()); \ |
23 call; \ | 23 call; \ |
24 if (HasStackOverflow()) return; \ | 24 if (HasStackOverflow()) return; \ |
25 } while (false) | 25 } while (false) |
26 | 26 |
27 | 27 |
28 class AsmWasmBuilderImpl : public AstVisitor { | 28 class AsmWasmBuilderImpl : public AstVisitor { |
29 public: | 29 public: |
30 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal) | 30 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
| 31 Handle<Object> foreign) |
31 : local_variables_(HashMap::PointersMatch, | 32 : local_variables_(HashMap::PointersMatch, |
32 ZoneHashMap::kDefaultHashMapCapacity, | 33 ZoneHashMap::kDefaultHashMapCapacity, |
33 ZoneAllocationPolicy(zone)), | 34 ZoneAllocationPolicy(zone)), |
34 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | 35 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, |
35 ZoneAllocationPolicy(zone)), | 36 ZoneAllocationPolicy(zone)), |
36 global_variables_(HashMap::PointersMatch, | 37 global_variables_(HashMap::PointersMatch, |
37 ZoneHashMap::kDefaultHashMapCapacity, | 38 ZoneHashMap::kDefaultHashMapCapacity, |
38 ZoneAllocationPolicy(zone)), | 39 ZoneAllocationPolicy(zone)), |
39 in_function_(false), | 40 in_function_(false), |
40 is_set_op_(false), | 41 is_set_op_(false), |
41 marking_exported(false), | 42 marking_exported(false), |
42 builder_(new (zone) WasmModuleBuilder(zone)), | 43 builder_(new (zone) WasmModuleBuilder(zone)), |
43 current_function_builder_(nullptr), | 44 current_function_builder_(nullptr), |
44 literal_(literal), | 45 literal_(literal), |
45 isolate_(isolate), | 46 isolate_(isolate), |
46 zone_(zone), | 47 zone_(zone), |
| 48 foreign_(foreign), |
47 cache_(TypeCache::Get()), | 49 cache_(TypeCache::Get()), |
48 breakable_blocks_(zone), | 50 breakable_blocks_(zone), |
49 block_size_(0), | 51 block_size_(0), |
50 init_function_index_(0), | 52 init_function_index_(0), |
51 next_table_index_(0), | 53 next_table_index_(0), |
52 function_tables_(HashMap::PointersMatch, | 54 function_tables_(HashMap::PointersMatch, |
53 ZoneHashMap::kDefaultHashMapCapacity, | 55 ZoneHashMap::kDefaultHashMapCapacity, |
54 ZoneAllocationPolicy(zone)), | 56 ZoneAllocationPolicy(zone)), |
55 imported_function_table_(this) { | 57 imported_function_table_(this) { |
56 InitializeAstVisitor(isolate); | 58 InitializeAstVisitor(isolate); |
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 function->AddParam(sig->GetParam(i)); | 554 function->AddParam(sig->GetParam(i)); |
553 } | 555 } |
554 return index; | 556 return index; |
555 } | 557 } |
556 } | 558 } |
557 }; | 559 }; |
558 | 560 |
559 void VisitAssignment(Assignment* expr) { | 561 void VisitAssignment(Assignment* expr) { |
560 bool in_init = false; | 562 bool in_init = false; |
561 if (!in_function_) { | 563 if (!in_function_) { |
| 564 BinaryOperation* binop = expr->value()->AsBinaryOperation(); |
| 565 if (binop != nullptr) { |
| 566 Property* prop = binop->left()->AsProperty(); |
| 567 DCHECK(prop != nullptr); |
| 568 LoadInitFunction(); |
| 569 is_set_op_ = true; |
| 570 RECURSE(Visit(expr->target())); |
| 571 DCHECK(!is_set_op_); |
| 572 if (binop->op() == Token::MUL) { |
| 573 DCHECK(binop->right()->IsLiteral()); |
| 574 DCHECK(binop->right()->AsLiteral()->raw_value()->AsNumber() == 1.0); |
| 575 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
| 576 VisitForeignVariable(true, prop); |
| 577 } else if (binop->op() == Token::BIT_OR) { |
| 578 DCHECK(binop->right()->IsLiteral()); |
| 579 DCHECK(binop->right()->AsLiteral()->raw_value()->AsNumber() == 0.0); |
| 580 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
| 581 VisitForeignVariable(false, prop); |
| 582 } else { |
| 583 UNREACHABLE(); |
| 584 } |
| 585 UnLoadInitFunction(); |
| 586 return; |
| 587 } |
562 // TODO(bradnelson): Get rid of this. | 588 // TODO(bradnelson): Get rid of this. |
563 if (TypeOf(expr->value()) == kAstStmt) { | 589 if (TypeOf(expr->value()) == kAstStmt) { |
564 Property* prop = expr->value()->AsProperty(); | 590 Property* prop = expr->value()->AsProperty(); |
565 if (prop != nullptr) { | 591 if (prop != nullptr) { |
566 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 592 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
567 if (vp != nullptr && vp->var()->IsParameter() && | 593 if (vp != nullptr && vp->var()->IsParameter() && |
568 vp->var()->index() == 1) { | 594 vp->var()->index() == 1) { |
569 VariableProxy* target = expr->target()->AsVariableProxy(); | 595 VariableProxy* target = expr->target()->AsVariableProxy(); |
570 if (target->bounds().lower->Is(Type::Function())) { | 596 if (target->bounds().lower->Is(Type::Function())) { |
571 const AstRawString* name = | 597 const AstRawString* name = |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 RECURSE(Visit(expr->value())); | 629 RECURSE(Visit(expr->value())); |
604 if (in_init) { | 630 if (in_init) { |
605 UnLoadInitFunction(); | 631 UnLoadInitFunction(); |
606 } | 632 } |
607 } | 633 } |
608 | 634 |
609 void VisitYield(Yield* expr) { UNREACHABLE(); } | 635 void VisitYield(Yield* expr) { UNREACHABLE(); } |
610 | 636 |
611 void VisitThrow(Throw* expr) { UNREACHABLE(); } | 637 void VisitThrow(Throw* expr) { UNREACHABLE(); } |
612 | 638 |
| 639 void VisitForeignVariable(bool is_float, Property* expr) { |
| 640 DCHECK(expr->obj()->AsVariableProxy()); |
| 641 DCHECK(expr->obj()->AsVariableProxy()->var()->location() == |
| 642 VariableLocation::PARAMETER); |
| 643 DCHECK(expr->obj()->AsVariableProxy()->var()->index() == 1); |
| 644 Literal* key_literal = expr->key()->AsLiteral(); |
| 645 DCHECK(key_literal != nullptr); |
| 646 if (!key_literal->value().is_null() && !foreign_.is_null() && |
| 647 foreign_->IsObject()) { |
| 648 Handle<Name> name = |
| 649 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); |
| 650 MaybeHandle<Object> maybe_value = i::Object::GetProperty(foreign_, name); |
| 651 if (!maybe_value.is_null()) { |
| 652 Handle<Object> value = maybe_value.ToHandleChecked(); |
| 653 if (is_float) { |
| 654 MaybeHandle<Object> maybe_nvalue = i::Object::ToNumber(value); |
| 655 if (!maybe_nvalue.is_null()) { |
| 656 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); |
| 657 if (nvalue->IsNumber()) { |
| 658 double val = nvalue->Number(); |
| 659 byte code[] = {WASM_F64(val)}; |
| 660 current_function_builder_->EmitCode(code, sizeof(code)); |
| 661 return; |
| 662 } |
| 663 } |
| 664 } else { |
| 665 MaybeHandle<Object> maybe_nvalue = |
| 666 i::Object::ToInt32(isolate_, value); |
| 667 if (!maybe_nvalue.is_null()) { |
| 668 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); |
| 669 if (nvalue->IsNumber()) { |
| 670 int32_t val = static_cast<int32_t>(nvalue->Number()); |
| 671 byte code[] = {WASM_I32(val)}; |
| 672 current_function_builder_->EmitCode(code, sizeof(code)); |
| 673 return; |
| 674 } |
| 675 } |
| 676 } |
| 677 } |
| 678 } |
| 679 if (is_float) { |
| 680 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; |
| 681 current_function_builder_->EmitCode(code, sizeof(code)); |
| 682 } else { |
| 683 byte code[] = {WASM_I32(0)}; |
| 684 current_function_builder_->EmitCode(code, sizeof(code)); |
| 685 } |
| 686 } |
| 687 |
613 void VisitProperty(Property* expr) { | 688 void VisitProperty(Property* expr) { |
614 Expression* obj = expr->obj(); | 689 Expression* obj = expr->obj(); |
615 DCHECK(obj->bounds().lower == obj->bounds().upper); | 690 DCHECK(obj->bounds().lower == obj->bounds().upper); |
616 Type* type = obj->bounds().lower; | 691 Type* type = obj->bounds().lower; |
617 MachineType mtype; | 692 MachineType mtype; |
618 int size; | 693 int size; |
619 if (type->Is(cache_.kUint8Array)) { | 694 if (type->Is(cache_.kUint8Array)) { |
620 mtype = MachineType::Uint8(); | 695 mtype = MachineType::Uint8(); |
621 size = 1; | 696 size = 1; |
622 } else if (type->Is(cache_.kInt8Array)) { | 697 } else if (type->Is(cache_.kInt8Array)) { |
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1166 ZoneHashMap functions_; | 1241 ZoneHashMap functions_; |
1167 ZoneHashMap global_variables_; | 1242 ZoneHashMap global_variables_; |
1168 bool in_function_; | 1243 bool in_function_; |
1169 bool is_set_op_; | 1244 bool is_set_op_; |
1170 bool marking_exported; | 1245 bool marking_exported; |
1171 WasmModuleBuilder* builder_; | 1246 WasmModuleBuilder* builder_; |
1172 WasmFunctionBuilder* current_function_builder_; | 1247 WasmFunctionBuilder* current_function_builder_; |
1173 FunctionLiteral* literal_; | 1248 FunctionLiteral* literal_; |
1174 Isolate* isolate_; | 1249 Isolate* isolate_; |
1175 Zone* zone_; | 1250 Zone* zone_; |
| 1251 Handle<Object> foreign_; |
1176 TypeCache const& cache_; | 1252 TypeCache const& cache_; |
1177 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1253 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
1178 int block_size_; | 1254 int block_size_; |
1179 uint16_t init_function_index_; | 1255 uint16_t init_function_index_; |
1180 uint32_t next_table_index_; | 1256 uint32_t next_table_index_; |
1181 ZoneHashMap function_tables_; | 1257 ZoneHashMap function_tables_; |
1182 ImportedFunctionTable imported_function_table_; | 1258 ImportedFunctionTable imported_function_table_; |
1183 | 1259 |
1184 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1260 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1185 | 1261 |
1186 private: | 1262 private: |
1187 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1263 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
1188 }; | 1264 }; |
1189 | 1265 |
1190 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1266 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
1191 FunctionLiteral* literal) | 1267 FunctionLiteral* literal, Handle<Object> foreign) |
1192 : isolate_(isolate), zone_(zone), literal_(literal) {} | 1268 : isolate_(isolate), zone_(zone), literal_(literal), foreign_(foreign) {} |
1193 | 1269 |
1194 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1270 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
1195 // that zone in constructor may be thrown away once wasm module is written. | 1271 // that zone in constructor may be thrown away once wasm module is written. |
1196 WasmModuleIndex* AsmWasmBuilder::Run() { | 1272 WasmModuleIndex* AsmWasmBuilder::Run() { |
1197 AsmWasmBuilderImpl impl(isolate_, zone_, literal_); | 1273 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_); |
1198 impl.Compile(); | 1274 impl.Compile(); |
1199 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1275 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
1200 return writer->WriteTo(zone_); | 1276 return writer->WriteTo(zone_); |
1201 } | 1277 } |
1202 } // namespace wasm | 1278 } // namespace wasm |
1203 } // namespace internal | 1279 } // namespace internal |
1204 } // namespace v8 | 1280 } // namespace v8 |
OLD | NEW |